1da853ecaSopenharmony_ci/* 2da853ecaSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3da853ecaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4da853ecaSopenharmony_ci * you may not use this file except in compliance with the License. 5da853ecaSopenharmony_ci * You may obtain a copy of the License at 6da853ecaSopenharmony_ci * 7da853ecaSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8da853ecaSopenharmony_ci * 9da853ecaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10da853ecaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11da853ecaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12da853ecaSopenharmony_ci * See the License for the specific language governing permissions and 13da853ecaSopenharmony_ci * limitations under the License. 14da853ecaSopenharmony_ci */ 15da853ecaSopenharmony_ci 16da853ecaSopenharmony_ci#include <iostream> 17da853ecaSopenharmony_ci#include <set> 18da853ecaSopenharmony_ci#include <thread> 19da853ecaSopenharmony_ci#include <malloc.h> 20da853ecaSopenharmony_ci#include "syspara/parameters.h" 21da853ecaSopenharmony_ci#include "securec.h" 22da853ecaSopenharmony_ci#include "avcodec_trace.h" 23da853ecaSopenharmony_ci#include "avcodec_log.h" 24da853ecaSopenharmony_ci#include "utils.h" 25da853ecaSopenharmony_ci#include "avcodec_codec_name.h" 26da853ecaSopenharmony_ci#include "fcodec.h" 27da853ecaSopenharmony_ci 28da853ecaSopenharmony_cinamespace OHOS { 29da853ecaSopenharmony_cinamespace MediaAVCodec { 30da853ecaSopenharmony_cinamespace Codec { 31da853ecaSopenharmony_cinamespace { 32da853ecaSopenharmony_ciconstexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "FCodec"}; 33da853ecaSopenharmony_ciconstexpr uint32_t INDEX_INPUT = 0; 34da853ecaSopenharmony_ciconstexpr uint32_t INDEX_OUTPUT = 1; 35da853ecaSopenharmony_ciconstexpr int32_t DEFAULT_IN_BUFFER_CNT = 4; 36da853ecaSopenharmony_ciconstexpr int32_t DEFAULT_OUT_SURFACE_CNT = 4; 37da853ecaSopenharmony_ciconstexpr int32_t DEFAULT_OUT_BUFFER_CNT = 3; 38da853ecaSopenharmony_ciconstexpr int32_t DEFAULT_MIN_BUFFER_CNT = 2; 39da853ecaSopenharmony_ciconstexpr uint32_t VIDEO_PIX_DEPTH_YUV = 3; 40da853ecaSopenharmony_ciconstexpr int32_t VIDEO_MIN_BUFFER_SIZE = 1474560; 41da853ecaSopenharmony_ciconstexpr int32_t VIDEO_MIN_SIZE = 2; 42da853ecaSopenharmony_ciconstexpr int32_t VIDEO_ALIGNMENT_SIZE = 2; 43da853ecaSopenharmony_ciconstexpr int32_t VIDEO_MAX_WIDTH_SIZE = 4096; 44da853ecaSopenharmony_ciconstexpr int32_t VIDEO_MAX_HEIGHT_SIZE = 4096; 45da853ecaSopenharmony_ciconstexpr int32_t DEFAULT_VIDEO_WIDTH = 1920; 46da853ecaSopenharmony_ciconstexpr int32_t DEFAULT_VIDEO_HEIGHT = 1080; 47da853ecaSopenharmony_ciconstexpr uint32_t DEFAULT_TRY_DECODE_TIME = 1; 48da853ecaSopenharmony_ciconstexpr uint32_t DEFAULT_TRY_REQ_TIME = 10; 49da853ecaSopenharmony_ciconstexpr uint32_t DEFAULT_DECODE_WAIT_TIME = 200; 50da853ecaSopenharmony_ciconstexpr int32_t VIDEO_INSTANCE_SIZE = 64; 51da853ecaSopenharmony_ciconstexpr int32_t VIDEO_BITRATE_MAX_SIZE = 300000000; 52da853ecaSopenharmony_ciconstexpr int32_t VIDEO_FRAMERATE_MAX_SIZE = 120; 53da853ecaSopenharmony_ciconstexpr int32_t VIDEO_BLOCKPERFRAME_SIZE = 36864; 54da853ecaSopenharmony_ciconstexpr int32_t VIDEO_BLOCKPERSEC_SIZE = 983040; 55da853ecaSopenharmony_ciconstexpr int32_t DEFAULT_THREAD_COUNT = 2; 56da853ecaSopenharmony_ci#ifdef BUILD_ENG_VERSION 57da853ecaSopenharmony_ciconstexpr uint32_t PATH_MAX_LEN = 128; 58da853ecaSopenharmony_ciconstexpr char DUMP_PATH[] = "/data/misc/fcodecdump"; 59da853ecaSopenharmony_ci#endif // BUILD_ENG_VERSION 60da853ecaSopenharmony_ciconstexpr struct { 61da853ecaSopenharmony_ci const std::string_view codecName; 62da853ecaSopenharmony_ci const std::string_view mimeType; 63da853ecaSopenharmony_ci const char *ffmpegCodec; 64da853ecaSopenharmony_ci const bool isEncoder; 65da853ecaSopenharmony_ci} SUPPORT_VCODEC[] = { 66da853ecaSopenharmony_ci {AVCodecCodecName::VIDEO_DECODER_AVC_NAME, CodecMimeType::VIDEO_AVC, "h264", false}, 67da853ecaSopenharmony_ci}; 68da853ecaSopenharmony_ciconstexpr uint32_t SUPPORT_VCODEC_NUM = sizeof(SUPPORT_VCODEC) / sizeof(SUPPORT_VCODEC[0]); 69da853ecaSopenharmony_ci} // namespace 70da853ecaSopenharmony_ciusing namespace OHOS::Media; 71da853ecaSopenharmony_ciFCodec::FCodec(const std::string &name) : codecName_(name), state_(State::UNINITIALIZED) 72da853ecaSopenharmony_ci{ 73da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 74da853ecaSopenharmony_ci AVCODEC_LOGD("Fcodec entered, state: Uninitialized"); 75da853ecaSopenharmony_ci} 76da853ecaSopenharmony_ci 77da853ecaSopenharmony_ciFCodec::~FCodec() 78da853ecaSopenharmony_ci{ 79da853ecaSopenharmony_ci ReleaseResource(); 80da853ecaSopenharmony_ci callback_ = nullptr; 81da853ecaSopenharmony_ci#ifdef BUILD_ENG_VERSION 82da853ecaSopenharmony_ci if (dumpInFile_ != nullptr) { 83da853ecaSopenharmony_ci dumpInFile_->close(); 84da853ecaSopenharmony_ci } 85da853ecaSopenharmony_ci if (dumpOutFile_ != nullptr) { 86da853ecaSopenharmony_ci dumpOutFile_->close(); 87da853ecaSopenharmony_ci } 88da853ecaSopenharmony_ci#endif // BUILD_ENG_VERSION 89da853ecaSopenharmony_ci mallopt(M_FLUSH_THREAD_CACHE, 0); 90da853ecaSopenharmony_ci} 91da853ecaSopenharmony_ci 92da853ecaSopenharmony_ci#ifdef BUILD_ENG_VERSION 93da853ecaSopenharmony_civoid FCodec::OpenDumpFile() 94da853ecaSopenharmony_ci{ 95da853ecaSopenharmony_ci std::string dumpModeStr = OHOS::system::GetParameter("fcodec.dump", "0"); 96da853ecaSopenharmony_ci AVCODEC_LOGI("dumpModeStr %{public}s", dumpModeStr.c_str()); 97da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(dumpModeStr.length() == 2, "dumpModeStr length should equal 2"); // 2 98da853ecaSopenharmony_ci char fileName[PATH_MAX_LEN] = {0}; 99da853ecaSopenharmony_ci int ret; 100da853ecaSopenharmony_ci if (dumpModeStr[0] == '1') { 101da853ecaSopenharmony_ci ret = sprintf_s(fileName, sizeof(fileName), "%s/input_%p.h264", DUMP_PATH, this); 102da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(ret > 0, "Fail to sprintf input fileName"); 103da853ecaSopenharmony_ci dumpInFile_ = std::make_shared<std::ofstream>(); 104da853ecaSopenharmony_ci dumpInFile_->open(fileName, std::ios::out | std::ios::binary); 105da853ecaSopenharmony_ci if (!dumpInFile_->is_open()) { 106da853ecaSopenharmony_ci AVCODEC_LOGW("fail open file %{public}s", fileName); 107da853ecaSopenharmony_ci dumpInFile_ = nullptr; 108da853ecaSopenharmony_ci } 109da853ecaSopenharmony_ci } 110da853ecaSopenharmony_ci 111da853ecaSopenharmony_ci if (dumpModeStr[1] == '1') { 112da853ecaSopenharmony_ci ret = sprintf_s(fileName, sizeof(fileName), "%s/output_%p.yuv", DUMP_PATH, this); 113da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(ret > 0, "Fail to sprintf output fileName"); 114da853ecaSopenharmony_ci dumpOutFile_ = std::make_shared<std::ofstream>(); 115da853ecaSopenharmony_ci dumpOutFile_->open(fileName, std::ios::out | std::ios::binary); 116da853ecaSopenharmony_ci if (!dumpOutFile_->is_open()) { 117da853ecaSopenharmony_ci AVCODEC_LOGW("fail open file %{public}s", fileName); 118da853ecaSopenharmony_ci dumpOutFile_ = nullptr; 119da853ecaSopenharmony_ci } 120da853ecaSopenharmony_ci } 121da853ecaSopenharmony_ci} 122da853ecaSopenharmony_ci#endif // BUILD_ENG_VERSION 123da853ecaSopenharmony_ci 124da853ecaSopenharmony_ciint32_t FCodec::Initialize() 125da853ecaSopenharmony_ci{ 126da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 127da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(!codecName_.empty(), AVCS_ERR_INVALID_VAL, "Init codec failed: empty name"); 128da853ecaSopenharmony_ci std::string fcodecName; 129da853ecaSopenharmony_ci std::string_view mime; 130da853ecaSopenharmony_ci for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) { 131da853ecaSopenharmony_ci if (SUPPORT_VCODEC[i].codecName == codecName_) { 132da853ecaSopenharmony_ci fcodecName = SUPPORT_VCODEC[i].ffmpegCodec; 133da853ecaSopenharmony_ci mime = SUPPORT_VCODEC[i].mimeType; 134da853ecaSopenharmony_ci break; 135da853ecaSopenharmony_ci } 136da853ecaSopenharmony_ci } 137da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(!fcodecName.empty(), AVCS_ERR_INVALID_VAL, 138da853ecaSopenharmony_ci "Init codec failed: not support name: %{public}s", codecName_.c_str()); 139da853ecaSopenharmony_ci format_.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_MIME, mime); 140da853ecaSopenharmony_ci format_.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, codecName_); 141da853ecaSopenharmony_ci avCodec_ = std::shared_ptr<AVCodec>(const_cast<AVCodec *>(avcodec_find_decoder_by_name(fcodecName.c_str())), 142da853ecaSopenharmony_ci [](void *ptr) {}); 143da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(avCodec_ != nullptr, AVCS_ERR_INVALID_VAL, 144da853ecaSopenharmony_ci "Init codec failed: cannot find codec with name %{public}s", codecName_.c_str()); 145da853ecaSopenharmony_ci sendTask_ = std::make_shared<TaskThread>("SendFrame"); 146da853ecaSopenharmony_ci sendTask_->RegisterHandler([this] { SendFrame(); }); 147da853ecaSopenharmony_ci receiveTask_ = std::make_shared<TaskThread>("ReceiveFrame"); 148da853ecaSopenharmony_ci receiveTask_->RegisterHandler([this] { ReceiveFrame(); }); 149da853ecaSopenharmony_ci#ifdef BUILD_ENG_VERSION 150da853ecaSopenharmony_ci OpenDumpFile(); 151da853ecaSopenharmony_ci#endif // BUILD_ENG_VERSION 152da853ecaSopenharmony_ci state_ = State::INITIALIZED; 153da853ecaSopenharmony_ci AVCODEC_LOGI("Init codec successful, state: Uninitialized -> Initialized"); 154da853ecaSopenharmony_ci return AVCS_ERR_OK; 155da853ecaSopenharmony_ci} 156da853ecaSopenharmony_ci 157da853ecaSopenharmony_civoid FCodec::ConfigureDefaultVal(const Format &format, const std::string_view &formatKey, int32_t minVal, 158da853ecaSopenharmony_ci int32_t maxVal) 159da853ecaSopenharmony_ci{ 160da853ecaSopenharmony_ci int32_t val32 = 0; 161da853ecaSopenharmony_ci if (format.GetIntValue(formatKey, val32) && val32 >= minVal && val32 <= maxVal) { 162da853ecaSopenharmony_ci format_.PutIntValue(formatKey, val32); 163da853ecaSopenharmony_ci } else { 164da853ecaSopenharmony_ci AVCODEC_LOGW("Set parameter failed: %{public}s, which minimum threshold=%{public}d, " 165da853ecaSopenharmony_ci "maximum threshold=%{public}d", 166da853ecaSopenharmony_ci std::string(formatKey).c_str(), minVal, maxVal); 167da853ecaSopenharmony_ci } 168da853ecaSopenharmony_ci} 169da853ecaSopenharmony_ci 170da853ecaSopenharmony_civoid FCodec::ConfigureSurface(const Format &format, const std::string_view &formatKey, FormatDataType formatType) 171da853ecaSopenharmony_ci{ 172da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(formatType == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32"); 173da853ecaSopenharmony_ci 174da853ecaSopenharmony_ci int32_t val = 0; 175da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail"); 176da853ecaSopenharmony_ci 177da853ecaSopenharmony_ci if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) { 178da853ecaSopenharmony_ci VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val); 179da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUVI420 || 180da853ecaSopenharmony_ci vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21, 181da853ecaSopenharmony_ci "Set parameter failed: pixel format value %{public}d invalid", val); 182da853ecaSopenharmony_ci outputPixelFmt_ = vpf; 183da853ecaSopenharmony_ci format_.PutIntValue(formatKey, val); 184da853ecaSopenharmony_ci } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) { 185da853ecaSopenharmony_ci VideoRotation sr = static_cast<VideoRotation>(val); 186da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 || 187da853ecaSopenharmony_ci sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270, 188da853ecaSopenharmony_ci "Set parameter failed: rotation angle value %{public}d invalid", val); 189da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val); 190da853ecaSopenharmony_ci } else if (formatKey == MediaDescriptionKey::MD_KEY_SCALE_TYPE) { 191da853ecaSopenharmony_ci ScalingMode scaleMode = static_cast<ScalingMode>(val); 192da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW || 193da853ecaSopenharmony_ci scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP, 194da853ecaSopenharmony_ci "Set parameter failed: scale type value %{public}d invalid", val); 195da853ecaSopenharmony_ci format_.PutIntValue(formatKey, val); 196da853ecaSopenharmony_ci } else { 197da853ecaSopenharmony_ci AVCODEC_LOGW("Set parameter failed: %{public}s, please check your parameter key", 198da853ecaSopenharmony_ci std::string(formatKey).c_str()); 199da853ecaSopenharmony_ci return; 200da853ecaSopenharmony_ci } 201da853ecaSopenharmony_ci AVCODEC_LOGI("Set parameter %{public}s success, val %{public}d", std::string(formatKey).c_str(), val); 202da853ecaSopenharmony_ci} 203da853ecaSopenharmony_ci 204da853ecaSopenharmony_ciint32_t FCodec::ConfigureContext(const Format &format) 205da853ecaSopenharmony_ci{ 206da853ecaSopenharmony_ci avCodecContext_ = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(avCodec_.get()), [](AVCodecContext *p) { 207da853ecaSopenharmony_ci if (p != nullptr) { 208da853ecaSopenharmony_ci if (p->extradata) { 209da853ecaSopenharmony_ci av_free(p->extradata); 210da853ecaSopenharmony_ci p->extradata = nullptr; 211da853ecaSopenharmony_ci } 212da853ecaSopenharmony_ci avcodec_free_context(&p); 213da853ecaSopenharmony_ci } 214da853ecaSopenharmony_ci }); 215da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(avCodecContext_ != nullptr, AVCS_ERR_INVALID_OPERATION, 216da853ecaSopenharmony_ci "Configure codec failed: Allocate context error"); 217da853ecaSopenharmony_ci avCodecContext_->codec_type = AVMEDIA_TYPE_VIDEO; 218da853ecaSopenharmony_ci format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_); 219da853ecaSopenharmony_ci format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_); 220da853ecaSopenharmony_ci format_.PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE, 221da853ecaSopenharmony_ci outputPixelFmt_ == VideoPixelFormat::RGBA ? width_ * VIDEO_PIX_DEPTH_RGBA : width_); 222da853ecaSopenharmony_ci format_.PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, height_); 223da853ecaSopenharmony_ci format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_); 224da853ecaSopenharmony_ci format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_); 225da853ecaSopenharmony_ci 226da853ecaSopenharmony_ci avCodecContext_->width = width_; 227da853ecaSopenharmony_ci avCodecContext_->height = height_; 228da853ecaSopenharmony_ci avCodecContext_->thread_count = DEFAULT_THREAD_COUNT; 229da853ecaSopenharmony_ci return AVCS_ERR_OK; 230da853ecaSopenharmony_ci} 231da853ecaSopenharmony_ci 232da853ecaSopenharmony_ciint32_t FCodec::Configure(const Format &format) 233da853ecaSopenharmony_ci{ 234da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 235da853ecaSopenharmony_ci if (state_ == State::UNINITIALIZED) { 236da853ecaSopenharmony_ci int32_t ret = Initialize(); 237da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Init codec failed"); 238da853ecaSopenharmony_ci } 239da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG((state_ == State::INITIALIZED), AVCS_ERR_INVALID_STATE, 240da853ecaSopenharmony_ci "Configure codec failed: not in Initialized state"); 241da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, DEFAULT_VIDEO_WIDTH); 242da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, DEFAULT_VIDEO_HEIGHT); 243da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_BUFFER_CNT); 244da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, DEFAULT_IN_BUFFER_CNT); 245da853ecaSopenharmony_ci for (auto &it : format.GetFormatMap()) { 246da853ecaSopenharmony_ci if (it.first == MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT) { 247da853ecaSopenharmony_ci isOutBufSetted_ = true; 248da853ecaSopenharmony_ci ConfigureDefaultVal(format, it.first, DEFAULT_MIN_BUFFER_CNT); 249da853ecaSopenharmony_ci } else if (it.first == MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT) { 250da853ecaSopenharmony_ci ConfigureDefaultVal(format, it.first, DEFAULT_MIN_BUFFER_CNT); 251da853ecaSopenharmony_ci } else if (it.first == MediaDescriptionKey::MD_KEY_WIDTH) { 252da853ecaSopenharmony_ci ConfigureDefaultVal(format, it.first, VIDEO_MIN_SIZE, VIDEO_MAX_WIDTH_SIZE); 253da853ecaSopenharmony_ci } else if (it.first == MediaDescriptionKey::MD_KEY_HEIGHT) { 254da853ecaSopenharmony_ci ConfigureDefaultVal(format, it.first, VIDEO_MIN_SIZE, VIDEO_MAX_HEIGHT_SIZE); 255da853ecaSopenharmony_ci } else if (it.first == MediaDescriptionKey::MD_KEY_BITRATE) { 256da853ecaSopenharmony_ci int64_t val64 = 0; 257da853ecaSopenharmony_ci format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, val64); 258da853ecaSopenharmony_ci format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, val64); 259da853ecaSopenharmony_ci } else if (it.first == MediaDescriptionKey::MD_KEY_FRAME_RATE) { 260da853ecaSopenharmony_ci double val = 0; 261da853ecaSopenharmony_ci format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, val); 262da853ecaSopenharmony_ci format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, val); 263da853ecaSopenharmony_ci } else if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT || 264da853ecaSopenharmony_ci it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE || 265da853ecaSopenharmony_ci it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) { 266da853ecaSopenharmony_ci ConfigureSurface(format, it.first, it.second.type); 267da853ecaSopenharmony_ci } else { 268da853ecaSopenharmony_ci AVCODEC_LOGW("Set parameter failed: size:%{public}s, unsupport key", it.first.data()); 269da853ecaSopenharmony_ci } 270da853ecaSopenharmony_ci } 271da853ecaSopenharmony_ci AVCODEC_LOGI("current pixel format %{public}d", static_cast<int32_t>(outputPixelFmt_)); 272da853ecaSopenharmony_ci int32_t ret = ConfigureContext(format); 273da853ecaSopenharmony_ci 274da853ecaSopenharmony_ci state_ = State::CONFIGURED; 275da853ecaSopenharmony_ci AVCODEC_LOGI("Configured codec successful: state: Initialized -> Configured"); 276da853ecaSopenharmony_ci return ret; 277da853ecaSopenharmony_ci} 278da853ecaSopenharmony_ci 279da853ecaSopenharmony_cibool FCodec::IsActive() const 280da853ecaSopenharmony_ci{ 281da853ecaSopenharmony_ci return state_ == State::RUNNING || state_ == State::FLUSHED || state_ == State::EOS; 282da853ecaSopenharmony_ci} 283da853ecaSopenharmony_ci 284da853ecaSopenharmony_civoid FCodec::ResetContext(bool isFlush) 285da853ecaSopenharmony_ci{ 286da853ecaSopenharmony_ci if (avCodecContext_ == nullptr) { 287da853ecaSopenharmony_ci return; 288da853ecaSopenharmony_ci } 289da853ecaSopenharmony_ci if (avCodecContext_->extradata) { 290da853ecaSopenharmony_ci av_free(avCodecContext_->extradata); 291da853ecaSopenharmony_ci avCodecContext_->extradata = nullptr; 292da853ecaSopenharmony_ci } 293da853ecaSopenharmony_ci avCodecContext_->coded_width = 0; 294da853ecaSopenharmony_ci avCodecContext_->coded_height = 0; 295da853ecaSopenharmony_ci avCodecContext_->extradata_size = 0; 296da853ecaSopenharmony_ci if (!isFlush) { 297da853ecaSopenharmony_ci avCodecContext_->width = 0; 298da853ecaSopenharmony_ci avCodecContext_->height = 0; 299da853ecaSopenharmony_ci avCodecContext_->get_buffer2 = nullptr; 300da853ecaSopenharmony_ci } 301da853ecaSopenharmony_ci} 302da853ecaSopenharmony_ci 303da853ecaSopenharmony_ciint32_t FCodec::Start() 304da853ecaSopenharmony_ci{ 305da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 306da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(callback_ != nullptr, AVCS_ERR_INVALID_OPERATION, "Start codec failed: callback is null"); 307da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG((state_ == State::CONFIGURED || state_ == State::FLUSHED), AVCS_ERR_INVALID_STATE, 308da853ecaSopenharmony_ci "Start codec failed: not in Configured or Flushed state"); 309da853ecaSopenharmony_ci if (state_ != State::FLUSHED) { 310da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(avcodec_open2(avCodecContext_.get(), avCodec_.get(), nullptr) == 0, AVCS_ERR_UNKNOWN, 311da853ecaSopenharmony_ci "Start codec failed: cannot open avcodec"); 312da853ecaSopenharmony_ci } 313da853ecaSopenharmony_ci if (!isBufferAllocated_) { 314da853ecaSopenharmony_ci cachedFrame_ = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame *p) { av_frame_free(&p); }); 315da853ecaSopenharmony_ci avPacket_ = std::shared_ptr<AVPacket>(av_packet_alloc(), [](AVPacket *p) { av_packet_free(&p); }); 316da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG((cachedFrame_ != nullptr && avPacket_ != nullptr), AVCS_ERR_UNKNOWN, 317da853ecaSopenharmony_ci "Start codec failed: cannot allocate frame or packet"); 318da853ecaSopenharmony_ci for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) { 319da853ecaSopenharmony_ci scaleData_[i] = nullptr; 320da853ecaSopenharmony_ci scaleLineSize_[i] = 0; 321da853ecaSopenharmony_ci } 322da853ecaSopenharmony_ci isConverted_ = false; 323da853ecaSopenharmony_ci int32_t ret = AllocateBuffers(); 324da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Start codec failed: cannot allocate buffers"); 325da853ecaSopenharmony_ci isBufferAllocated_ = true; 326da853ecaSopenharmony_ci } 327da853ecaSopenharmony_ci state_ = State::RUNNING; 328da853ecaSopenharmony_ci InitBuffers(); 329da853ecaSopenharmony_ci isSendEos_ = false; 330da853ecaSopenharmony_ci sendTask_->Start(); 331da853ecaSopenharmony_ci receiveTask_->Start(); 332da853ecaSopenharmony_ci AVCODEC_LOGI("Start codec successful, state: Running"); 333da853ecaSopenharmony_ci return AVCS_ERR_OK; 334da853ecaSopenharmony_ci} 335da853ecaSopenharmony_ci 336da853ecaSopenharmony_civoid FCodec::InitBuffers() 337da853ecaSopenharmony_ci{ 338da853ecaSopenharmony_ci inputAvailQue_->SetActive(true); 339da853ecaSopenharmony_ci codecAvailQue_->SetActive(true); 340da853ecaSopenharmony_ci if (sInfo_.surface != nullptr) { 341da853ecaSopenharmony_ci renderAvailQue_->SetActive(true); 342da853ecaSopenharmony_ci } 343da853ecaSopenharmony_ci if (buffers_[INDEX_INPUT].size() > 0) { 344da853ecaSopenharmony_ci for (uint32_t i = 0; i < buffers_[INDEX_INPUT].size(); i++) { 345da853ecaSopenharmony_ci buffers_[INDEX_INPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_USER; 346da853ecaSopenharmony_ci callback_->OnInputBufferAvailable(i, buffers_[INDEX_INPUT][i]->avBuffer_); 347da853ecaSopenharmony_ci AVCODEC_LOGI("OnInputBufferAvailable frame index = %{public}d, owner = %{public}d", i, 348da853ecaSopenharmony_ci buffers_[INDEX_INPUT][i]->owner_.load()); 349da853ecaSopenharmony_ci } 350da853ecaSopenharmony_ci } 351da853ecaSopenharmony_ci if (buffers_[INDEX_OUTPUT].size() <= 0) { 352da853ecaSopenharmony_ci return; 353da853ecaSopenharmony_ci } 354da853ecaSopenharmony_ci if (sInfo_.surface == nullptr) { 355da853ecaSopenharmony_ci for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) { 356da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_CODEC; 357da853ecaSopenharmony_ci codecAvailQue_->Push(i); 358da853ecaSopenharmony_ci } 359da853ecaSopenharmony_ci } else { 360da853ecaSopenharmony_ci for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) { 361da853ecaSopenharmony_ci std::shared_ptr<FSurfaceMemory> surfaceMemory = buffers_[INDEX_OUTPUT][i]->sMemory_; 362da853ecaSopenharmony_ci if (surfaceMemory->GetSurfaceBuffer() == nullptr) { 363da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_SURFACE; 364da853ecaSopenharmony_ci renderAvailQue_->Push(i); 365da853ecaSopenharmony_ci } else { 366da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT][i]->owner_ = FBuffer::Owner::OWNED_BY_CODEC; 367da853ecaSopenharmony_ci codecAvailQue_->Push(i); 368da853ecaSopenharmony_ci } 369da853ecaSopenharmony_ci } 370da853ecaSopenharmony_ci } 371da853ecaSopenharmony_ci} 372da853ecaSopenharmony_ci 373da853ecaSopenharmony_civoid FCodec::ResetData() 374da853ecaSopenharmony_ci{ 375da853ecaSopenharmony_ci if (scaleData_[0] != nullptr) { 376da853ecaSopenharmony_ci if (isConverted_) { 377da853ecaSopenharmony_ci av_free(scaleData_[0]); 378da853ecaSopenharmony_ci isConverted_ = false; 379da853ecaSopenharmony_ci scale_.reset(); 380da853ecaSopenharmony_ci } 381da853ecaSopenharmony_ci for (int32_t i = 0; i < AV_NUM_DATA_POINTERS; i++) { 382da853ecaSopenharmony_ci scaleData_[i] = nullptr; 383da853ecaSopenharmony_ci scaleLineSize_[i] = 0; 384da853ecaSopenharmony_ci } 385da853ecaSopenharmony_ci } 386da853ecaSopenharmony_ci} 387da853ecaSopenharmony_ci 388da853ecaSopenharmony_civoid FCodec::ResetBuffers() 389da853ecaSopenharmony_ci{ 390da853ecaSopenharmony_ci inputAvailQue_->Clear(); 391da853ecaSopenharmony_ci std::unique_lock<std::mutex> iLock(inputMutex_); 392da853ecaSopenharmony_ci synIndex_ = std::nullopt; 393da853ecaSopenharmony_ci iLock.unlock(); 394da853ecaSopenharmony_ci codecAvailQue_->Clear(); 395da853ecaSopenharmony_ci if (sInfo_.surface != nullptr) { 396da853ecaSopenharmony_ci renderAvailQue_->Clear(); 397da853ecaSopenharmony_ci renderSurfaceBufferMap_.clear(); 398da853ecaSopenharmony_ci } 399da853ecaSopenharmony_ci ResetData(); 400da853ecaSopenharmony_ci av_frame_unref(cachedFrame_.get()); 401da853ecaSopenharmony_ci av_packet_unref(avPacket_.get()); 402da853ecaSopenharmony_ci} 403da853ecaSopenharmony_ci 404da853ecaSopenharmony_civoid FCodec::StopThread() 405da853ecaSopenharmony_ci{ 406da853ecaSopenharmony_ci if (sendTask_ != nullptr && inputAvailQue_ != nullptr) { 407da853ecaSopenharmony_ci std::unique_lock<std::mutex> sLock(sendMutex_); 408da853ecaSopenharmony_ci sendCv_.notify_one(); 409da853ecaSopenharmony_ci sLock.unlock(); 410da853ecaSopenharmony_ci inputAvailQue_->SetActive(false, false); 411da853ecaSopenharmony_ci sendTask_->Stop(); 412da853ecaSopenharmony_ci } 413da853ecaSopenharmony_ci if (receiveTask_ != nullptr && codecAvailQue_ != nullptr) { 414da853ecaSopenharmony_ci std::unique_lock<std::mutex> rLock(recvMutex_); 415da853ecaSopenharmony_ci recvCv_.notify_one(); 416da853ecaSopenharmony_ci rLock.unlock(); 417da853ecaSopenharmony_ci codecAvailQue_->SetActive(false, false); 418da853ecaSopenharmony_ci receiveTask_->Stop(); 419da853ecaSopenharmony_ci } 420da853ecaSopenharmony_ci if (sInfo_.surface != nullptr && renderAvailQue_ != nullptr) { 421da853ecaSopenharmony_ci renderAvailQue_->SetActive(false, false); 422da853ecaSopenharmony_ci } 423da853ecaSopenharmony_ci} 424da853ecaSopenharmony_ci 425da853ecaSopenharmony_ciint32_t FCodec::Stop() 426da853ecaSopenharmony_ci{ 427da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 428da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG((IsActive()), AVCS_ERR_INVALID_STATE, "Stop codec failed: not in executing state"); 429da853ecaSopenharmony_ci state_ = State::STOPPING; 430da853ecaSopenharmony_ci AVCODEC_LOGI("step into STOPPING status"); 431da853ecaSopenharmony_ci std::unique_lock<std::mutex> sLock(sendMutex_); 432da853ecaSopenharmony_ci sendCv_.notify_one(); 433da853ecaSopenharmony_ci sLock.unlock(); 434da853ecaSopenharmony_ci inputAvailQue_->SetActive(false, false); 435da853ecaSopenharmony_ci sendTask_->Stop(); 436da853ecaSopenharmony_ci 437da853ecaSopenharmony_ci if (sInfo_.surface != nullptr) { 438da853ecaSopenharmony_ci renderAvailQue_->SetActive(false, false); 439da853ecaSopenharmony_ci } 440da853ecaSopenharmony_ci std::unique_lock<std::mutex> rLock(recvMutex_); 441da853ecaSopenharmony_ci recvCv_.notify_one(); 442da853ecaSopenharmony_ci rLock.unlock(); 443da853ecaSopenharmony_ci codecAvailQue_->SetActive(false, false); 444da853ecaSopenharmony_ci receiveTask_->Stop(); 445da853ecaSopenharmony_ci avcodec_close(avCodecContext_.get()); 446da853ecaSopenharmony_ci ResetContext(true); 447da853ecaSopenharmony_ci ResetBuffers(); 448da853ecaSopenharmony_ci state_ = State::CONFIGURED; 449da853ecaSopenharmony_ci AVCODEC_LOGI("Stop codec successful, state: Configured"); 450da853ecaSopenharmony_ci return AVCS_ERR_OK; 451da853ecaSopenharmony_ci} 452da853ecaSopenharmony_ci 453da853ecaSopenharmony_ciint32_t FCodec::Flush() 454da853ecaSopenharmony_ci{ 455da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 456da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG((state_ == State::RUNNING || state_ == State::EOS), AVCS_ERR_INVALID_STATE, 457da853ecaSopenharmony_ci "Flush codec failed: not in running or Eos state"); 458da853ecaSopenharmony_ci state_ = State::FLUSHING; 459da853ecaSopenharmony_ci AVCODEC_LOGI("step into FLUSHING status"); 460da853ecaSopenharmony_ci std::unique_lock<std::mutex> sLock(sendMutex_); 461da853ecaSopenharmony_ci sendCv_.notify_one(); 462da853ecaSopenharmony_ci sLock.unlock(); 463da853ecaSopenharmony_ci inputAvailQue_->SetActive(false, false); 464da853ecaSopenharmony_ci sendTask_->Pause(); 465da853ecaSopenharmony_ci 466da853ecaSopenharmony_ci if (sInfo_.surface != nullptr) { 467da853ecaSopenharmony_ci renderAvailQue_->SetActive(false, false); 468da853ecaSopenharmony_ci } 469da853ecaSopenharmony_ci std::unique_lock<std::mutex> rLock(recvMutex_); 470da853ecaSopenharmony_ci recvCv_.notify_one(); 471da853ecaSopenharmony_ci rLock.unlock(); 472da853ecaSopenharmony_ci codecAvailQue_->SetActive(false, false); 473da853ecaSopenharmony_ci receiveTask_->Pause(); 474da853ecaSopenharmony_ci 475da853ecaSopenharmony_ci avcodec_flush_buffers(avCodecContext_.get()); 476da853ecaSopenharmony_ci ResetContext(true); 477da853ecaSopenharmony_ci ResetBuffers(); 478da853ecaSopenharmony_ci state_ = State::FLUSHED; 479da853ecaSopenharmony_ci AVCODEC_LOGI("Flush codec successful, state: Flushed"); 480da853ecaSopenharmony_ci return AVCS_ERR_OK; 481da853ecaSopenharmony_ci} 482da853ecaSopenharmony_ci 483da853ecaSopenharmony_ciint32_t FCodec::Reset() 484da853ecaSopenharmony_ci{ 485da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 486da853ecaSopenharmony_ci AVCODEC_LOGI("Reset codec called"); 487da853ecaSopenharmony_ci int32_t ret = Release(); 488da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Reset codec failed: cannot release codec"); 489da853ecaSopenharmony_ci ret = Initialize(); 490da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Reset codec failed: cannot init codec"); 491da853ecaSopenharmony_ci AVCODEC_LOGI("Reset codec successful, state: Initialized"); 492da853ecaSopenharmony_ci return AVCS_ERR_OK; 493da853ecaSopenharmony_ci} 494da853ecaSopenharmony_ci 495da853ecaSopenharmony_civoid FCodec::ReleaseResource() 496da853ecaSopenharmony_ci{ 497da853ecaSopenharmony_ci StopThread(); 498da853ecaSopenharmony_ci if (avCodecContext_ != nullptr) { 499da853ecaSopenharmony_ci avcodec_close(avCodecContext_.get()); 500da853ecaSopenharmony_ci ResetContext(); 501da853ecaSopenharmony_ci } 502da853ecaSopenharmony_ci ReleaseBuffers(); 503da853ecaSopenharmony_ci format_ = Format(); 504da853ecaSopenharmony_ci if (sInfo_.surface != nullptr) { 505da853ecaSopenharmony_ci sInfo_.surface->CleanCache(); 506da853ecaSopenharmony_ci AVCODEC_LOGI("surface cleancache success"); 507da853ecaSopenharmony_ci int ret = UnRegisterListenerToSurface(sInfo_.surface); 508da853ecaSopenharmony_ci if (ret != 0) { 509da853ecaSopenharmony_ci callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN); 510da853ecaSopenharmony_ci state_ = State::ERROR; 511da853ecaSopenharmony_ci } 512da853ecaSopenharmony_ci } 513da853ecaSopenharmony_ci sInfo_.surface = nullptr; 514da853ecaSopenharmony_ci} 515da853ecaSopenharmony_ci 516da853ecaSopenharmony_ciint32_t FCodec::Release() 517da853ecaSopenharmony_ci{ 518da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 519da853ecaSopenharmony_ci state_ = State::STOPPING; 520da853ecaSopenharmony_ci AVCODEC_LOGI("step into STOPPING status"); 521da853ecaSopenharmony_ci ReleaseResource(); 522da853ecaSopenharmony_ci state_ = State::UNINITIALIZED; 523da853ecaSopenharmony_ci AVCODEC_LOGI("Release codec successful, state: Uninitialized"); 524da853ecaSopenharmony_ci return AVCS_ERR_OK; 525da853ecaSopenharmony_ci} 526da853ecaSopenharmony_ci 527da853ecaSopenharmony_civoid FCodec::SetSurfaceParameter(const Format &format, const std::string_view &formatKey, FormatDataType formatType) 528da853ecaSopenharmony_ci{ 529da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(formatType == FORMAT_TYPE_INT32, "Set parameter failed: type should be int32"); 530da853ecaSopenharmony_ci int32_t val = 0; 531da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(format.GetIntValue(formatKey, val), "Set parameter failed: get value fail"); 532da853ecaSopenharmony_ci if (formatKey == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) { 533da853ecaSopenharmony_ci VideoPixelFormat vpf = static_cast<VideoPixelFormat>(val); 534da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(vpf == VideoPixelFormat::RGBA || vpf == VideoPixelFormat::YUVI420 || 535da853ecaSopenharmony_ci vpf == VideoPixelFormat::NV12 || vpf == VideoPixelFormat::NV21, 536da853ecaSopenharmony_ci "Set parameter failed: pixel format value %{public}d invalid", val); 537da853ecaSopenharmony_ci outputPixelFmt_ = vpf; 538da853ecaSopenharmony_ci { 539da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(formatMutex_); 540da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val); 541da853ecaSopenharmony_ci } 542da853ecaSopenharmony_ci GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(vpf); 543da853ecaSopenharmony_ci std::lock_guard<std::mutex> sLock(surfaceMutex_); 544da853ecaSopenharmony_ci sInfo_.requestConfig.format = surfacePixelFmt; 545da853ecaSopenharmony_ci } else if (formatKey == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE) { 546da853ecaSopenharmony_ci VideoRotation sr = static_cast<VideoRotation>(val); 547da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(sr == VideoRotation::VIDEO_ROTATION_0 || sr == VideoRotation::VIDEO_ROTATION_90 || 548da853ecaSopenharmony_ci sr == VideoRotation::VIDEO_ROTATION_180 || sr == VideoRotation::VIDEO_ROTATION_270, 549da853ecaSopenharmony_ci "Set parameter failed: rotation angle value %{public}d invalid", val); 550da853ecaSopenharmony_ci { 551da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(formatMutex_); 552da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val); 553da853ecaSopenharmony_ci } 554da853ecaSopenharmony_ci std::lock_guard<std::mutex> sLock(surfaceMutex_); 555da853ecaSopenharmony_ci sInfo_.surface->SetTransform(TranslateSurfaceRotation(sr)); 556da853ecaSopenharmony_ci } else if (formatKey == MediaDescriptionKey::MD_KEY_SCALE_TYPE) { 557da853ecaSopenharmony_ci ScalingMode scaleMode = static_cast<ScalingMode>(val); 558da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(scaleMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW || 559da853ecaSopenharmony_ci scaleMode == ScalingMode::SCALING_MODE_SCALE_CROP, 560da853ecaSopenharmony_ci "Set parameter failed: scale type value %{public}d invalid", val); 561da853ecaSopenharmony_ci { 562da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(formatMutex_); 563da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val); 564da853ecaSopenharmony_ci } 565da853ecaSopenharmony_ci std::lock_guard<std::mutex> sLock(surfaceMutex_); 566da853ecaSopenharmony_ci sInfo_.scalingMode = scaleMode; 567da853ecaSopenharmony_ci } else { 568da853ecaSopenharmony_ci AVCODEC_LOGW("Set parameter failed: %{public}s", std::string(formatKey).c_str()); 569da853ecaSopenharmony_ci return; 570da853ecaSopenharmony_ci } 571da853ecaSopenharmony_ci AVCODEC_LOGI("Set parameter %{public}s success, val %{public}d", std::string(formatKey).c_str(), val); 572da853ecaSopenharmony_ci} 573da853ecaSopenharmony_ci 574da853ecaSopenharmony_ciint32_t FCodec::SetParameter(const Format &format) 575da853ecaSopenharmony_ci{ 576da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 577da853ecaSopenharmony_ci for (auto &it : format.GetFormatMap()) { 578da853ecaSopenharmony_ci if (sInfo_.surface != nullptr && it.second.type == FORMAT_TYPE_INT32) { 579da853ecaSopenharmony_ci if (it.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT || 580da853ecaSopenharmony_ci it.first == MediaDescriptionKey::MD_KEY_ROTATION_ANGLE || 581da853ecaSopenharmony_ci it.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) { 582da853ecaSopenharmony_ci SetSurfaceParameter(format, it.first, it.second.type); 583da853ecaSopenharmony_ci } 584da853ecaSopenharmony_ci } else { 585da853ecaSopenharmony_ci AVCODEC_LOGW("Current Version, %{public}s is not supported", it.first.data()); 586da853ecaSopenharmony_ci } 587da853ecaSopenharmony_ci } 588da853ecaSopenharmony_ci AVCODEC_LOGI("Set parameter successful"); 589da853ecaSopenharmony_ci return AVCS_ERR_OK; 590da853ecaSopenharmony_ci} 591da853ecaSopenharmony_ci 592da853ecaSopenharmony_ciint32_t FCodec::GetOutputFormat(Format &format) 593da853ecaSopenharmony_ci{ 594da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 595da853ecaSopenharmony_ci if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_BITRATE)) { 596da853ecaSopenharmony_ci if (avCodecContext_ != nullptr) { 597da853ecaSopenharmony_ci format_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, avCodecContext_->bit_rate); 598da853ecaSopenharmony_ci } 599da853ecaSopenharmony_ci } 600da853ecaSopenharmony_ci if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_FRAME_RATE)) { 601da853ecaSopenharmony_ci if (avCodecContext_ != nullptr && avCodecContext_->framerate.den > 0) { 602da853ecaSopenharmony_ci double value = static_cast<double>(avCodecContext_->framerate.num) / 603da853ecaSopenharmony_ci static_cast<double>(avCodecContext_->framerate.den); 604da853ecaSopenharmony_ci format_.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, value); 605da853ecaSopenharmony_ci } 606da853ecaSopenharmony_ci } 607da853ecaSopenharmony_ci if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE)) { 608da853ecaSopenharmony_ci int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE); 609da853ecaSopenharmony_ci int32_t maxInputSize = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) / UV_SCALE_FACTOR); 610da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, maxInputSize); 611da853ecaSopenharmony_ci } 612da853ecaSopenharmony_ci { 613da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(formatMutex_); 614da853ecaSopenharmony_ci format = format_; 615da853ecaSopenharmony_ci } 616da853ecaSopenharmony_ci AVCODEC_LOGI("Get outputFormat successful"); 617da853ecaSopenharmony_ci return AVCS_ERR_OK; 618da853ecaSopenharmony_ci} 619da853ecaSopenharmony_ci 620da853ecaSopenharmony_civoid FCodec::CalculateBufferSize() 621da853ecaSopenharmony_ci{ 622da853ecaSopenharmony_ci int32_t stride = AlignUp(width_, VIDEO_ALIGN_SIZE); 623da853ecaSopenharmony_ci outputBufferSize_ = static_cast<int32_t>((stride * height_ * VIDEO_PIX_DEPTH_YUV) / UV_SCALE_FACTOR); 624da853ecaSopenharmony_ci inputBufferSize_ = std::max(VIDEO_MIN_BUFFER_SIZE, outputBufferSize_); 625da853ecaSopenharmony_ci if (outputPixelFmt_ == VideoPixelFormat::RGBA) { 626da853ecaSopenharmony_ci outputBufferSize_ = static_cast<int32_t>(stride * height_ * VIDEO_PIX_DEPTH_RGBA); 627da853ecaSopenharmony_ci } 628da853ecaSopenharmony_ci AVCODEC_LOGI("width = %{public}d, height = %{public}d, stride = %{public}d, Input buffer size = %{public}d, output " 629da853ecaSopenharmony_ci "buffer size=%{public}d", 630da853ecaSopenharmony_ci width_, height_, stride, inputBufferSize_, outputBufferSize_); 631da853ecaSopenharmony_ci} 632da853ecaSopenharmony_ci 633da853ecaSopenharmony_ciint32_t FCodec::AllocateInputBuffer(int32_t bufferCnt, int32_t inBufferSize) 634da853ecaSopenharmony_ci{ 635da853ecaSopenharmony_ci int32_t valBufferCnt = 0; 636da853ecaSopenharmony_ci for (int32_t i = 0; i < bufferCnt; i++) { 637da853ecaSopenharmony_ci std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>(); 638da853ecaSopenharmony_ci std::shared_ptr<AVAllocator> allocator = 639da853ecaSopenharmony_ci AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE); 640da853ecaSopenharmony_ci CHECK_AND_CONTINUE_LOG(allocator != nullptr, "input buffer %{public}d allocator is nullptr", i); 641da853ecaSopenharmony_ci buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, inBufferSize); 642da853ecaSopenharmony_ci CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate input buffer failed, index=%{public}d", i); 643da853ecaSopenharmony_ci AVCODEC_LOGI("Allocate input buffer success: index=%{public}d, size=%{public}d", i, 644da853ecaSopenharmony_ci buf->avBuffer_->memory_->GetCapacity()); 645da853ecaSopenharmony_ci buffers_[INDEX_INPUT].emplace_back(buf); 646da853ecaSopenharmony_ci valBufferCnt++; 647da853ecaSopenharmony_ci } 648da853ecaSopenharmony_ci if (valBufferCnt < DEFAULT_MIN_BUFFER_CNT) { 649da853ecaSopenharmony_ci AVCODEC_LOGE("Allocate input buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt); 650da853ecaSopenharmony_ci buffers_[INDEX_INPUT].clear(); 651da853ecaSopenharmony_ci return AVCS_ERR_NO_MEMORY; 652da853ecaSopenharmony_ci } 653da853ecaSopenharmony_ci return AVCS_ERR_OK; 654da853ecaSopenharmony_ci} 655da853ecaSopenharmony_ci 656da853ecaSopenharmony_ciint32_t FCodec::SetSurfaceCfg(int32_t bufferCnt) 657da853ecaSopenharmony_ci{ 658da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(sInfo_.surface->SetQueueSize(bufferCnt) == OHOS::SurfaceError::SURFACE_ERROR_OK, 659da853ecaSopenharmony_ci AVCS_ERR_NO_MEMORY, "Surface set QueueSize=%{public}d failed", bufferCnt); 660da853ecaSopenharmony_ci if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) { 661da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(VideoPixelFormat::NV12)); 662da853ecaSopenharmony_ci } 663da853ecaSopenharmony_ci int32_t val32 = 0; 664da853ecaSopenharmony_ci format_.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, val32); 665da853ecaSopenharmony_ci GraphicPixelFormat surfacePixelFmt = TranslateSurfaceFormat(static_cast<VideoPixelFormat>(val32)); 666da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(surfacePixelFmt != GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BUTT, AVCS_ERR_UNSUPPORT, 667da853ecaSopenharmony_ci "Failed to allocate output buffer: unsupported surface format"); 668da853ecaSopenharmony_ci sInfo_.requestConfig.width = width_; 669da853ecaSopenharmony_ci sInfo_.requestConfig.height = height_; 670da853ecaSopenharmony_ci sInfo_.requestConfig.format = surfacePixelFmt; 671da853ecaSopenharmony_ci 672da853ecaSopenharmony_ci format_.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, val32); 673da853ecaSopenharmony_ci sInfo_.scalingMode = static_cast<ScalingMode>(val32); 674da853ecaSopenharmony_ci format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, val32); 675da853ecaSopenharmony_ci sInfo_.surface->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(val32))); 676da853ecaSopenharmony_ci return AVCS_ERR_OK; 677da853ecaSopenharmony_ci} 678da853ecaSopenharmony_ci 679da853ecaSopenharmony_ciint32_t FCodec::AllocateOutputBuffer(int32_t bufferCnt, int32_t outBufferSize) 680da853ecaSopenharmony_ci{ 681da853ecaSopenharmony_ci int32_t valBufferCnt = 0; 682da853ecaSopenharmony_ci if (sInfo_.surface) { 683da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(SetSurfaceCfg(bufferCnt) == AVCS_ERR_OK, AVCS_ERR_UNKNOWN, "SetSurfaceCfg failed"); 684da853ecaSopenharmony_ci } 685da853ecaSopenharmony_ci for (int i = 0; i < bufferCnt; i++) { 686da853ecaSopenharmony_ci std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>(); 687da853ecaSopenharmony_ci if (sInfo_.surface == nullptr) { 688da853ecaSopenharmony_ci std::shared_ptr<AVAllocator> allocator = 689da853ecaSopenharmony_ci AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE); 690da853ecaSopenharmony_ci CHECK_AND_CONTINUE_LOG(allocator != nullptr, "output buffer %{public}d allocator is nullptr", i); 691da853ecaSopenharmony_ci buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, outBufferSize); 692da853ecaSopenharmony_ci AVCODEC_LOGI("Allocate output share buffer success: index=%{public}d, size=%{public}d", i, 693da853ecaSopenharmony_ci buf->avBuffer_->memory_->GetCapacity()); 694da853ecaSopenharmony_ci } else { 695da853ecaSopenharmony_ci buf->sMemory_ = std::make_shared<FSurfaceMemory>(&sInfo_); 696da853ecaSopenharmony_ci CHECK_AND_CONTINUE_LOG(buf->sMemory_->GetSurfaceBuffer() != nullptr, 697da853ecaSopenharmony_ci "output surface memory %{public}d create fail", i); 698da853ecaSopenharmony_ci outAVBuffer4Surface_.emplace_back(AVBuffer::CreateAVBuffer()); 699da853ecaSopenharmony_ci buf->avBuffer_ = AVBuffer::CreateAVBuffer(buf->sMemory_->GetBase(), buf->sMemory_->GetSize()); 700da853ecaSopenharmony_ci AVCODEC_LOGI("Allocate output surface buffer success: index=%{public}d, size=%{public}d, " 701da853ecaSopenharmony_ci "stride=%{public}d", 702da853ecaSopenharmony_ci i, buf->sMemory_->GetSize(), buf->sMemory_->GetSurfaceBufferStride()); 703da853ecaSopenharmony_ci } 704da853ecaSopenharmony_ci CHECK_AND_CONTINUE_LOG(buf->avBuffer_ != nullptr, "Allocate output buffer failed, index=%{public}d", i); 705da853ecaSopenharmony_ci 706da853ecaSopenharmony_ci buf->width_ = width_; 707da853ecaSopenharmony_ci buf->height_ = height_; 708da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT].emplace_back(buf); 709da853ecaSopenharmony_ci valBufferCnt++; 710da853ecaSopenharmony_ci } 711da853ecaSopenharmony_ci if (valBufferCnt < DEFAULT_MIN_BUFFER_CNT) { 712da853ecaSopenharmony_ci AVCODEC_LOGE("Allocate output buffer failed: only %{public}d buffer is allocated, no memory", valBufferCnt); 713da853ecaSopenharmony_ci buffers_[INDEX_INPUT].clear(); 714da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT].clear(); 715da853ecaSopenharmony_ci return AVCS_ERR_NO_MEMORY; 716da853ecaSopenharmony_ci } 717da853ecaSopenharmony_ci return AVCS_ERR_OK; 718da853ecaSopenharmony_ci} 719da853ecaSopenharmony_ci 720da853ecaSopenharmony_ciint32_t FCodec::AllocateBuffers() 721da853ecaSopenharmony_ci{ 722da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 723da853ecaSopenharmony_ci CalculateBufferSize(); 724da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(inputBufferSize_ > 0 && outputBufferSize_ > 0, AVCS_ERR_INVALID_VAL, 725da853ecaSopenharmony_ci "Allocate buffer with input size=%{public}d, output size=%{public}d failed", 726da853ecaSopenharmony_ci inputBufferSize_, outputBufferSize_); 727da853ecaSopenharmony_ci if (sInfo_.surface != nullptr && isOutBufSetted_ == false) { 728da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, DEFAULT_OUT_SURFACE_CNT); 729da853ecaSopenharmony_ci } 730da853ecaSopenharmony_ci int32_t inputBufferCnt = 0; 731da853ecaSopenharmony_ci int32_t outputBufferCnt = 0; 732da853ecaSopenharmony_ci format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, inputBufferCnt); 733da853ecaSopenharmony_ci format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, outputBufferCnt); 734da853ecaSopenharmony_ci inputAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("inputAvailQue", inputBufferCnt); 735da853ecaSopenharmony_ci codecAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("codecAvailQue", outputBufferCnt); 736da853ecaSopenharmony_ci if (sInfo_.surface != nullptr) { 737da853ecaSopenharmony_ci renderAvailQue_ = std::make_shared<BlockQueue<uint32_t>>("renderAvailQue", outputBufferCnt); 738da853ecaSopenharmony_ci } 739da853ecaSopenharmony_ci if (AllocateInputBuffer(inputBufferCnt, inputBufferSize_) == AVCS_ERR_NO_MEMORY || 740da853ecaSopenharmony_ci AllocateOutputBuffer(outputBufferCnt, outputBufferSize_) == AVCS_ERR_NO_MEMORY) { 741da853ecaSopenharmony_ci return AVCS_ERR_NO_MEMORY; 742da853ecaSopenharmony_ci } 743da853ecaSopenharmony_ci AVCODEC_LOGI("Allocate buffers successful"); 744da853ecaSopenharmony_ci return AVCS_ERR_OK; 745da853ecaSopenharmony_ci} 746da853ecaSopenharmony_ci 747da853ecaSopenharmony_ciint32_t FCodec::UpdateBuffers(uint32_t index, int32_t bufferSize, uint32_t bufferType) 748da853ecaSopenharmony_ci{ 749da853ecaSopenharmony_ci int32_t curBufSize = buffers_[bufferType][index]->avBuffer_->memory_->GetCapacity(); 750da853ecaSopenharmony_ci if (bufferSize != curBufSize) { 751da853ecaSopenharmony_ci std::shared_ptr<FBuffer> buf = std::make_shared<FBuffer>(); 752da853ecaSopenharmony_ci std::shared_ptr<AVAllocator> allocator = 753da853ecaSopenharmony_ci AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE); 754da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(allocator != nullptr, AVCS_ERR_NO_MEMORY, "buffer %{public}d allocator is nullptr", 755da853ecaSopenharmony_ci index); 756da853ecaSopenharmony_ci buf->avBuffer_ = AVBuffer::CreateAVBuffer(allocator, bufferSize); 757da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(buf->avBuffer_ != nullptr, AVCS_ERR_NO_MEMORY, 758da853ecaSopenharmony_ci "Buffer allocate failed, index=%{public}d", index); 759da853ecaSopenharmony_ci AVCODEC_LOGI("update share buffer success: bufferType=%{public}u, index=%{public}d, size=%{public}d", 760da853ecaSopenharmony_ci bufferType, index, buf->avBuffer_->memory_->GetCapacity()); 761da853ecaSopenharmony_ci 762da853ecaSopenharmony_ci if (bufferType == INDEX_INPUT) { 763da853ecaSopenharmony_ci buf->owner_ = FBuffer::Owner::OWNED_BY_USER; 764da853ecaSopenharmony_ci } else { 765da853ecaSopenharmony_ci buf->owner_ = FBuffer::Owner::OWNED_BY_CODEC; 766da853ecaSopenharmony_ci } 767da853ecaSopenharmony_ci buffers_[bufferType][index] = buf; 768da853ecaSopenharmony_ci } 769da853ecaSopenharmony_ci return AVCS_ERR_OK; 770da853ecaSopenharmony_ci} 771da853ecaSopenharmony_ci 772da853ecaSopenharmony_ciint32_t FCodec::UpdateSurfaceMemory(uint32_t index) 773da853ecaSopenharmony_ci{ 774da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 775da853ecaSopenharmony_ci std::unique_lock<std::mutex> oLock(outputMutex_); 776da853ecaSopenharmony_ci std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index]; 777da853ecaSopenharmony_ci oLock.unlock(); 778da853ecaSopenharmony_ci if (width_ != outputBuffer->width_ || height_ != outputBuffer->height_) { 779da853ecaSopenharmony_ci std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_; 780da853ecaSopenharmony_ci surfaceMemory->SetNeedRender(false); 781da853ecaSopenharmony_ci surfaceMemory->ReleaseSurfaceBuffer(); 782da853ecaSopenharmony_ci while (state_ == State::RUNNING) { 783da853ecaSopenharmony_ci std::unique_lock<std::mutex> sLock(surfaceMutex_); 784da853ecaSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer(); 785da853ecaSopenharmony_ci sLock.unlock(); 786da853ecaSopenharmony_ci if (surfaceBuffer != nullptr) { 787da853ecaSopenharmony_ci break; 788da853ecaSopenharmony_ci } 789da853ecaSopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_REQ_TIME)); 790da853ecaSopenharmony_ci } 791da853ecaSopenharmony_ci 792da853ecaSopenharmony_ci outputBuffer->avBuffer_ = 793da853ecaSopenharmony_ci AVBuffer::CreateAVBuffer(outputBuffer->sMemory_->GetBase(), outputBuffer->sMemory_->GetSize()); 794da853ecaSopenharmony_ci outputBuffer->width_ = width_; 795da853ecaSopenharmony_ci outputBuffer->height_ = height_; 796da853ecaSopenharmony_ci } 797da853ecaSopenharmony_ci 798da853ecaSopenharmony_ci return AVCS_ERR_OK; 799da853ecaSopenharmony_ci} 800da853ecaSopenharmony_ci 801da853ecaSopenharmony_ciint32_t FCodec::CheckFormatChange(uint32_t index, int width, int height) 802da853ecaSopenharmony_ci{ 803da853ecaSopenharmony_ci if (width_ != width || height_ != height) { 804da853ecaSopenharmony_ci AVCODEC_LOGI("format change, width: %{public}d->%{public}d, height: %{public}d->%{public}d", width_, width, 805da853ecaSopenharmony_ci height_, height); 806da853ecaSopenharmony_ci width_ = width; 807da853ecaSopenharmony_ci height_ = height; 808da853ecaSopenharmony_ci ResetData(); 809da853ecaSopenharmony_ci scale_ = nullptr; 810da853ecaSopenharmony_ci CalculateBufferSize(); 811da853ecaSopenharmony_ci { 812da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(formatMutex_); 813da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, width_); 814da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, height_); 815da853ecaSopenharmony_ci format_.PutIntValue(OHOS::Media::Tag::VIDEO_STRIDE, 816da853ecaSopenharmony_ci outputPixelFmt_ == VideoPixelFormat::RGBA ? width_ * VIDEO_PIX_DEPTH_RGBA : width_); 817da853ecaSopenharmony_ci format_.PutIntValue(OHOS::Media::Tag::VIDEO_SLICE_HEIGHT, height_); 818da853ecaSopenharmony_ci format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_WIDTH, width_); 819da853ecaSopenharmony_ci format_.PutIntValue(OHOS::Media::Tag::VIDEO_PIC_HEIGHT, height_); 820da853ecaSopenharmony_ci } 821da853ecaSopenharmony_ci if (sInfo_.surface) { 822da853ecaSopenharmony_ci std::lock_guard<std::mutex> sLock(surfaceMutex_); 823da853ecaSopenharmony_ci sInfo_.requestConfig.width = width_; 824da853ecaSopenharmony_ci sInfo_.requestConfig.height = height_; 825da853ecaSopenharmony_ci } 826da853ecaSopenharmony_ci callback_->OnOutputFormatChanged(format_); 827da853ecaSopenharmony_ci } 828da853ecaSopenharmony_ci if (sInfo_.surface == nullptr) { 829da853ecaSopenharmony_ci std::lock_guard<std::mutex> oLock(outputMutex_); 830da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG((UpdateBuffers(index, outputBufferSize_, INDEX_OUTPUT) == AVCS_ERR_OK), 831da853ecaSopenharmony_ci AVCS_ERR_NO_MEMORY, "Update output buffer failed, index=%{public}u", index); 832da853ecaSopenharmony_ci } else { 833da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG((UpdateSurfaceMemory(index) == AVCS_ERR_OK), AVCS_ERR_NO_MEMORY, 834da853ecaSopenharmony_ci "Update buffer failed"); 835da853ecaSopenharmony_ci } 836da853ecaSopenharmony_ci return AVCS_ERR_OK; 837da853ecaSopenharmony_ci} 838da853ecaSopenharmony_ci 839da853ecaSopenharmony_civoid FCodec::ReleaseBuffers() 840da853ecaSopenharmony_ci{ 841da853ecaSopenharmony_ci ResetData(); 842da853ecaSopenharmony_ci if (!isBufferAllocated_) { 843da853ecaSopenharmony_ci return; 844da853ecaSopenharmony_ci } 845da853ecaSopenharmony_ci 846da853ecaSopenharmony_ci inputAvailQue_->Clear(); 847da853ecaSopenharmony_ci std::unique_lock<std::mutex> iLock(inputMutex_); 848da853ecaSopenharmony_ci buffers_[INDEX_INPUT].clear(); 849da853ecaSopenharmony_ci synIndex_ = std::nullopt; 850da853ecaSopenharmony_ci iLock.unlock(); 851da853ecaSopenharmony_ci 852da853ecaSopenharmony_ci std::unique_lock<std::mutex> oLock(outputMutex_); 853da853ecaSopenharmony_ci codecAvailQue_->Clear(); 854da853ecaSopenharmony_ci if (sInfo_.surface != nullptr) { 855da853ecaSopenharmony_ci renderAvailQue_->Clear(); 856da853ecaSopenharmony_ci renderSurfaceBufferMap_.clear(); 857da853ecaSopenharmony_ci for (uint32_t i = 0; i < buffers_[INDEX_OUTPUT].size(); i++) { 858da853ecaSopenharmony_ci std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][i]; 859da853ecaSopenharmony_ci if (outputBuffer->owner_ == FBuffer::Owner::OWNED_BY_CODEC) { 860da853ecaSopenharmony_ci std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_; 861da853ecaSopenharmony_ci surfaceMemory->SetNeedRender(false); 862da853ecaSopenharmony_ci surfaceMemory->ReleaseSurfaceBuffer(); 863da853ecaSopenharmony_ci outputBuffer->owner_ = FBuffer::Owner::OWNED_BY_SURFACE; 864da853ecaSopenharmony_ci } 865da853ecaSopenharmony_ci } 866da853ecaSopenharmony_ci } 867da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT].clear(); 868da853ecaSopenharmony_ci outAVBuffer4Surface_.clear(); 869da853ecaSopenharmony_ci oLock.unlock(); 870da853ecaSopenharmony_ci isBufferAllocated_ = false; 871da853ecaSopenharmony_ci} 872da853ecaSopenharmony_ci 873da853ecaSopenharmony_ciint32_t FCodec::QueueInputBuffer(uint32_t index) 874da853ecaSopenharmony_ci{ 875da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 876da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(state_ == State::RUNNING, AVCS_ERR_INVALID_STATE, 877da853ecaSopenharmony_ci "Queue input buffer failed: not in Running state"); 878da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_INPUT].size(), AVCS_ERR_INVALID_VAL, 879da853ecaSopenharmony_ci "Queue input buffer failed with bad index, index=%{public}u, buffer_size=%{public}zu", 880da853ecaSopenharmony_ci index, buffers_[INDEX_INPUT].size()); 881da853ecaSopenharmony_ci std::shared_ptr<FBuffer> inputBuffer = buffers_[INDEX_INPUT][index]; 882da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(inputBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER, AVCS_ERR_INVALID_OPERATION, 883da853ecaSopenharmony_ci "Queue input buffer failed: buffer with index=%{public}u is not available", index); 884da853ecaSopenharmony_ci 885da853ecaSopenharmony_ci inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_CODEC; 886da853ecaSopenharmony_ci std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_; 887da853ecaSopenharmony_ci if (synIndex_) { 888da853ecaSopenharmony_ci const std::shared_ptr<AVBuffer> &curAVBuffer = buffers_[INDEX_INPUT][synIndex_.value()]->avBuffer_; 889da853ecaSopenharmony_ci int32_t curAVBufferSize = curAVBuffer->memory_->GetSize(); 890da853ecaSopenharmony_ci int32_t inputAVBufferSize = inputAVBuffer->memory_->GetSize(); 891da853ecaSopenharmony_ci if ((curAVBufferSize + inputAVBufferSize <= curAVBuffer->memory_->GetCapacity()) && 892da853ecaSopenharmony_ci memcpy_s(curAVBuffer->memory_->GetAddr() + curAVBufferSize, inputAVBufferSize, 893da853ecaSopenharmony_ci inputAVBuffer->memory_->GetAddr(), inputAVBufferSize) == EOK) { 894da853ecaSopenharmony_ci curAVBuffer->memory_->SetSize(curAVBufferSize + inputAVBufferSize); 895da853ecaSopenharmony_ci curAVBuffer->flag_ = inputAVBuffer->flag_; 896da853ecaSopenharmony_ci curAVBuffer->pts_ = inputAVBuffer->pts_; 897da853ecaSopenharmony_ci 898da853ecaSopenharmony_ci if (inputAVBuffer->flag_ != AVCODEC_BUFFER_FLAG_CODEC_DATA && 899da853ecaSopenharmony_ci inputAVBuffer->flag_ != AVCODEC_BUFFER_FLAG_PARTIAL_FRAME) { 900da853ecaSopenharmony_ci inputAvailQue_->Push(synIndex_.value()); 901da853ecaSopenharmony_ci synIndex_ = std::nullopt; 902da853ecaSopenharmony_ci } 903da853ecaSopenharmony_ci inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER; 904da853ecaSopenharmony_ci callback_->OnInputBufferAvailable(index, inputAVBuffer); 905da853ecaSopenharmony_ci return AVCS_ERR_OK; 906da853ecaSopenharmony_ci } else { 907da853ecaSopenharmony_ci AVCODEC_LOGE("packet size %{public}d over buffer size %{public}d", curAVBufferSize + inputAVBufferSize, 908da853ecaSopenharmony_ci curAVBuffer->memory_->GetCapacity()); 909da853ecaSopenharmony_ci callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY); 910da853ecaSopenharmony_ci state_ = State::ERROR; 911da853ecaSopenharmony_ci return AVCS_ERR_NO_MEMORY; 912da853ecaSopenharmony_ci } 913da853ecaSopenharmony_ci } else { 914da853ecaSopenharmony_ci if ((inputAVBuffer->flag_ == AVCODEC_BUFFER_FLAG_CODEC_DATA) || 915da853ecaSopenharmony_ci (inputAVBuffer->flag_ == AVCODEC_BUFFER_FLAG_PARTIAL_FRAME)) { 916da853ecaSopenharmony_ci synIndex_ = index; 917da853ecaSopenharmony_ci } else { 918da853ecaSopenharmony_ci inputAvailQue_->Push(index); 919da853ecaSopenharmony_ci } 920da853ecaSopenharmony_ci } 921da853ecaSopenharmony_ci 922da853ecaSopenharmony_ci return AVCS_ERR_OK; 923da853ecaSopenharmony_ci} 924da853ecaSopenharmony_ci 925da853ecaSopenharmony_civoid FCodec::SendFrame() 926da853ecaSopenharmony_ci{ 927da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(state_ != State::STOPPING && state_ != State::FLUSHING, "Invalid state"); 928da853ecaSopenharmony_ci if (state_ != State::RUNNING || isSendEos_) { 929da853ecaSopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME)); 930da853ecaSopenharmony_ci return; 931da853ecaSopenharmony_ci } 932da853ecaSopenharmony_ci uint32_t index = inputAvailQue_->Front(); 933da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state"); 934da853ecaSopenharmony_ci std::shared_ptr<FBuffer> &inputBuffer = buffers_[INDEX_INPUT][index]; 935da853ecaSopenharmony_ci std::shared_ptr<AVBuffer> &inputAVBuffer = inputBuffer->avBuffer_; 936da853ecaSopenharmony_ci if (inputAVBuffer->flag_ & AVCODEC_BUFFER_FLAG_EOS) { 937da853ecaSopenharmony_ci avPacket_->data = nullptr; 938da853ecaSopenharmony_ci avPacket_->size = 0; 939da853ecaSopenharmony_ci avPacket_->pts = 0; 940da853ecaSopenharmony_ci std::unique_lock<std::mutex> sendLock(sendMutex_); 941da853ecaSopenharmony_ci isSendEos_ = true; 942da853ecaSopenharmony_ci sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME)); 943da853ecaSopenharmony_ci AVCODEC_LOGI("Send eos end"); 944da853ecaSopenharmony_ci } else { 945da853ecaSopenharmony_ci avPacket_->data = inputAVBuffer->memory_->GetAddr(); 946da853ecaSopenharmony_ci avPacket_->size = static_cast<int32_t>(inputAVBuffer->memory_->GetSize()); 947da853ecaSopenharmony_ci avPacket_->pts = inputAVBuffer->pts_; 948da853ecaSopenharmony_ci } 949da853ecaSopenharmony_ci std::unique_lock<std::mutex> sLock(syncMutex_); 950da853ecaSopenharmony_ci int ret = avcodec_send_packet(avCodecContext_.get(), avPacket_.get()); 951da853ecaSopenharmony_ci sLock.unlock(); 952da853ecaSopenharmony_ci if (ret == 0 || ret == AVERROR_INVALIDDATA) { 953da853ecaSopenharmony_ci EXPECT_AND_LOGW(ret == AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str()); 954da853ecaSopenharmony_ci std::unique_lock<std::mutex> recvLock(recvMutex_); 955da853ecaSopenharmony_ci recvCv_.notify_one(); 956da853ecaSopenharmony_ci recvLock.unlock(); 957da853ecaSopenharmony_ci inputAvailQue_->Pop(); 958da853ecaSopenharmony_ci inputBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER; 959da853ecaSopenharmony_ci#ifdef BUILD_ENG_VERSION 960da853ecaSopenharmony_ci if (dumpInFile_ && dumpInFile_->is_open()) { 961da853ecaSopenharmony_ci dumpInFile_->write(reinterpret_cast<char *>(inputAVBuffer->memory_->GetAddr()), 962da853ecaSopenharmony_ci static_cast<int32_t>(inputAVBuffer->memory_->GetSize())); 963da853ecaSopenharmony_ci } 964da853ecaSopenharmony_ci#endif // BUILD_ENG_VERSION 965da853ecaSopenharmony_ci callback_->OnInputBufferAvailable(index, inputAVBuffer); 966da853ecaSopenharmony_ci } else if (ret == AVERROR(EAGAIN)) { 967da853ecaSopenharmony_ci std::unique_lock<std::mutex> sendLock(sendMutex_); 968da853ecaSopenharmony_ci isSendWait_ = true; 969da853ecaSopenharmony_ci sendCv_.wait_for(sendLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME)); 970da853ecaSopenharmony_ci } else { 971da853ecaSopenharmony_ci AVCODEC_LOGE("Cannot send frame to codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str()); 972da853ecaSopenharmony_ci callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN); 973da853ecaSopenharmony_ci state_ = State::ERROR; 974da853ecaSopenharmony_ci } 975da853ecaSopenharmony_ci} 976da853ecaSopenharmony_ci 977da853ecaSopenharmony_ciint32_t FCodec::FillFrameBuffer(const std::shared_ptr<FBuffer> &frameBuffer) 978da853ecaSopenharmony_ci{ 979da853ecaSopenharmony_ci VideoPixelFormat targetPixelFmt = outputPixelFmt_; 980da853ecaSopenharmony_ci if (outputPixelFmt_ == VideoPixelFormat::UNKNOWN) { 981da853ecaSopenharmony_ci targetPixelFmt = sInfo_.surface ? VideoPixelFormat::NV12 : ConvertPixelFormatFromFFmpeg(cachedFrame_->format); 982da853ecaSopenharmony_ci } 983da853ecaSopenharmony_ci AVPixelFormat ffmpegFormat = ConvertPixelFormatToFFmpeg(targetPixelFmt); 984da853ecaSopenharmony_ci int32_t ret; 985da853ecaSopenharmony_ci if (ffmpegFormat == static_cast<AVPixelFormat>(cachedFrame_->format)) { 986da853ecaSopenharmony_ci for (int32_t i = 0; cachedFrame_->linesize[i] > 0; i++) { 987da853ecaSopenharmony_ci scaleData_[i] = cachedFrame_->data[i]; 988da853ecaSopenharmony_ci scaleLineSize_[i] = cachedFrame_->linesize[i]; 989da853ecaSopenharmony_ci } 990da853ecaSopenharmony_ci } else { 991da853ecaSopenharmony_ci ret = ConvertVideoFrame(&scale_, cachedFrame_, scaleData_, scaleLineSize_, ffmpegFormat); 992da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Scale video frame failed: %{public}d", ret); 993da853ecaSopenharmony_ci isConverted_ = true; 994da853ecaSopenharmony_ci } 995da853ecaSopenharmony_ci { 996da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(formatMutex_); 997da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(targetPixelFmt)); 998da853ecaSopenharmony_ci } 999da853ecaSopenharmony_ci std::shared_ptr<AVMemory> &bufferMemory = frameBuffer->avBuffer_->memory_; 1000da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(bufferMemory != nullptr, AVCS_ERR_INVALID_VAL, "bufferMemory is nullptr"); 1001da853ecaSopenharmony_ci bufferMemory->SetSize(0); 1002da853ecaSopenharmony_ci if (sInfo_.surface) { 1003da853ecaSopenharmony_ci struct SurfaceInfo surfaceInfo; 1004da853ecaSopenharmony_ci surfaceInfo.surfaceStride = static_cast<uint32_t>(frameBuffer->sMemory_->GetSurfaceBufferStride()); 1005da853ecaSopenharmony_ci surfaceInfo.surfaceFence = frameBuffer->sMemory_->GetFence(); 1006da853ecaSopenharmony_ci surfaceInfo.scaleData = scaleData_; 1007da853ecaSopenharmony_ci surfaceInfo.scaleLineSize = scaleLineSize_; 1008da853ecaSopenharmony_ci ret = WriteSurfaceData(bufferMemory, surfaceInfo, format_); 1009da853ecaSopenharmony_ci } else { 1010da853ecaSopenharmony_ci ret = WriteBufferData(bufferMemory, scaleData_, scaleLineSize_, format_); 1011da853ecaSopenharmony_ci } 1012da853ecaSopenharmony_ci frameBuffer->avBuffer_->pts_ = cachedFrame_->pts; 1013da853ecaSopenharmony_ci AVCODEC_LOGD("Fill frame buffer successful"); 1014da853ecaSopenharmony_ci return ret; 1015da853ecaSopenharmony_ci} 1016da853ecaSopenharmony_ci 1017da853ecaSopenharmony_civoid FCodec::FramePostProcess(std::shared_ptr<FBuffer> &frameBuffer, uint32_t index, int32_t status, int ret) 1018da853ecaSopenharmony_ci{ 1019da853ecaSopenharmony_ci if (status == AVCS_ERR_OK) { 1020da853ecaSopenharmony_ci codecAvailQue_->Pop(); 1021da853ecaSopenharmony_ci frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_USER; 1022da853ecaSopenharmony_ci if (sInfo_.surface) { 1023da853ecaSopenharmony_ci outAVBuffer4Surface_[index]->pts_ = frameBuffer->avBuffer_->pts_; 1024da853ecaSopenharmony_ci outAVBuffer4Surface_[index]->flag_ = frameBuffer->avBuffer_->flag_; 1025da853ecaSopenharmony_ci } 1026da853ecaSopenharmony_ci if (ret == AVERROR_EOF) { 1027da853ecaSopenharmony_ci std::unique_lock<std::mutex> sLock(syncMutex_); 1028da853ecaSopenharmony_ci avcodec_flush_buffers(avCodecContext_.get()); 1029da853ecaSopenharmony_ci sLock.unlock(); 1030da853ecaSopenharmony_ci } else { 1031da853ecaSopenharmony_ci if (isSendWait_) { 1032da853ecaSopenharmony_ci std::lock_guard<std::mutex> sLock(sendMutex_); 1033da853ecaSopenharmony_ci isSendWait_ = false; 1034da853ecaSopenharmony_ci sendCv_.notify_one(); 1035da853ecaSopenharmony_ci } 1036da853ecaSopenharmony_ci } 1037da853ecaSopenharmony_ci callback_->OnOutputBufferAvailable(index, 1038da853ecaSopenharmony_ci sInfo_.surface ? outAVBuffer4Surface_[index] : frameBuffer->avBuffer_); 1039da853ecaSopenharmony_ci } else if (status == AVCS_ERR_UNSUPPORT) { 1040da853ecaSopenharmony_ci AVCODEC_LOGE("Recevie frame from codec failed: OnError"); 1041da853ecaSopenharmony_ci callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNSUPPORT); 1042da853ecaSopenharmony_ci state_ = State::ERROR; 1043da853ecaSopenharmony_ci } else { 1044da853ecaSopenharmony_ci AVCODEC_LOGE("Recevie frame from codec failed"); 1045da853ecaSopenharmony_ci callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN); 1046da853ecaSopenharmony_ci state_ = State::ERROR; 1047da853ecaSopenharmony_ci } 1048da853ecaSopenharmony_ci} 1049da853ecaSopenharmony_ci 1050da853ecaSopenharmony_civoid FCodec::DumpOutputBuffer() 1051da853ecaSopenharmony_ci{ 1052da853ecaSopenharmony_ci AVCODEC_LOGD("cur decNum: %{public}u", decNum_); 1053da853ecaSopenharmony_ci if (decNum_ == 0) { 1054da853ecaSopenharmony_ci callback_->OnOutputFormatChanged(format_); 1055da853ecaSopenharmony_ci } 1056da853ecaSopenharmony_ci decNum_++; 1057da853ecaSopenharmony_ci#ifdef BUILD_ENG_VERSION 1058da853ecaSopenharmony_ci if (!dumpOutFile_ || !dumpOutFile_->is_open()) { 1059da853ecaSopenharmony_ci return; 1060da853ecaSopenharmony_ci } 1061da853ecaSopenharmony_ci for (int32_t i = 0; i < cachedFrame_->height; i++) { 1062da853ecaSopenharmony_ci dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[0] + i * cachedFrame_->linesize[0]), 1063da853ecaSopenharmony_ci static_cast<int32_t>(cachedFrame_->width)); 1064da853ecaSopenharmony_ci } 1065da853ecaSopenharmony_ci for (int32_t i = 0; i < cachedFrame_->height / 2; i++) { // 2 1066da853ecaSopenharmony_ci dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[1] + i * cachedFrame_->linesize[1]), 1067da853ecaSopenharmony_ci static_cast<int32_t>(cachedFrame_->width / 2)); // 2 1068da853ecaSopenharmony_ci } 1069da853ecaSopenharmony_ci for (int32_t i = 0; i < cachedFrame_->height / 2; i++) { // 2 1070da853ecaSopenharmony_ci dumpOutFile_->write(reinterpret_cast<char *>(cachedFrame_->data[2] + i * cachedFrame_->linesize[2]), 1071da853ecaSopenharmony_ci static_cast<int32_t>(cachedFrame_->width / 2)); // 2 1072da853ecaSopenharmony_ci } 1073da853ecaSopenharmony_ci#endif // BUILD_ENG_VERSION 1074da853ecaSopenharmony_ci} 1075da853ecaSopenharmony_ci 1076da853ecaSopenharmony_civoid FCodec::ReceiveFrame() 1077da853ecaSopenharmony_ci{ 1078da853ecaSopenharmony_ci if (state_ == State::STOPPING || state_ == State::FLUSHING) { 1079da853ecaSopenharmony_ci return; 1080da853ecaSopenharmony_ci } else if (state_ != State::RUNNING) { 1081da853ecaSopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_TRY_DECODE_TIME)); 1082da853ecaSopenharmony_ci return; 1083da853ecaSopenharmony_ci } 1084da853ecaSopenharmony_ci auto index = codecAvailQue_->Front(); 1085da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state"); 1086da853ecaSopenharmony_ci std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index]; 1087da853ecaSopenharmony_ci std::unique_lock<std::mutex> sLock(syncMutex_); 1088da853ecaSopenharmony_ci int ret = avcodec_receive_frame(avCodecContext_.get(), cachedFrame_.get()); 1089da853ecaSopenharmony_ci sLock.unlock(); 1090da853ecaSopenharmony_ci int32_t status = AVCS_ERR_OK; 1091da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(ret != AVERROR_INVALIDDATA, "ffmpeg ret = %{public}s", AVStrError(ret).c_str()); 1092da853ecaSopenharmony_ci if (ret >= 0) { 1093da853ecaSopenharmony_ci DumpOutputBuffer(); 1094da853ecaSopenharmony_ci if (CheckFormatChange(index, cachedFrame_->width, cachedFrame_->height) == AVCS_ERR_OK) { 1095da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state"); 1096da853ecaSopenharmony_ci frameBuffer = buffers_[INDEX_OUTPUT][index]; 1097da853ecaSopenharmony_ci status = FillFrameBuffer(frameBuffer); 1098da853ecaSopenharmony_ci } else { 1099da853ecaSopenharmony_ci CHECK_AND_RETURN_LOG(state_ == State::RUNNING, "Not in running state"); 1100da853ecaSopenharmony_ci callback_->OnError(AVCODEC_ERROR_EXTEND_START, AVCS_ERR_NO_MEMORY); 1101da853ecaSopenharmony_ci return; 1102da853ecaSopenharmony_ci } 1103da853ecaSopenharmony_ci frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_NONE; 1104da853ecaSopenharmony_ci } else if (ret == AVERROR_EOF) { 1105da853ecaSopenharmony_ci AVCODEC_LOGI("Receive eos"); 1106da853ecaSopenharmony_ci frameBuffer->avBuffer_->flag_ = AVCODEC_BUFFER_FLAG_EOS; 1107da853ecaSopenharmony_ci frameBuffer->avBuffer_->memory_->SetSize(0); 1108da853ecaSopenharmony_ci state_ = State::EOS; 1109da853ecaSopenharmony_ci } else if (ret == AVERROR(EAGAIN)) { 1110da853ecaSopenharmony_ci std::unique_lock<std::mutex> sendLock(sendMutex_); 1111da853ecaSopenharmony_ci if (isSendWait_ || isSendEos_) { 1112da853ecaSopenharmony_ci isSendWait_ = false; 1113da853ecaSopenharmony_ci sendCv_.notify_one(); 1114da853ecaSopenharmony_ci } 1115da853ecaSopenharmony_ci sendLock.unlock(); 1116da853ecaSopenharmony_ci std::unique_lock<std::mutex> recvLock(recvMutex_); 1117da853ecaSopenharmony_ci recvCv_.wait_for(recvLock, std::chrono::milliseconds(DEFAULT_DECODE_WAIT_TIME)); 1118da853ecaSopenharmony_ci return; 1119da853ecaSopenharmony_ci } else { 1120da853ecaSopenharmony_ci AVCODEC_LOGE("Cannot recv frame from codec: ffmpeg ret = %{public}s", AVStrError(ret).c_str()); 1121da853ecaSopenharmony_ci callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_UNKNOWN); 1122da853ecaSopenharmony_ci state_ = State::ERROR; 1123da853ecaSopenharmony_ci return; 1124da853ecaSopenharmony_ci } 1125da853ecaSopenharmony_ci FramePostProcess(frameBuffer, index, status, ret); 1126da853ecaSopenharmony_ci} 1127da853ecaSopenharmony_ci 1128da853ecaSopenharmony_civoid FCodec::FindAvailIndex(uint32_t index) 1129da853ecaSopenharmony_ci{ 1130da853ecaSopenharmony_ci uint32_t curQueSize = renderAvailQue_->Size(); 1131da853ecaSopenharmony_ci for (uint32_t i = 0u; i < curQueSize; i++) { 1132da853ecaSopenharmony_ci uint32_t num = renderAvailQue_->Pop(); 1133da853ecaSopenharmony_ci if (num == index) { 1134da853ecaSopenharmony_ci break; 1135da853ecaSopenharmony_ci } else { 1136da853ecaSopenharmony_ci renderAvailQue_->Push(num); 1137da853ecaSopenharmony_ci } 1138da853ecaSopenharmony_ci } 1139da853ecaSopenharmony_ci} 1140da853ecaSopenharmony_ci 1141da853ecaSopenharmony_ciint32_t FCodec::ReleaseOutputBuffer(uint32_t index) 1142da853ecaSopenharmony_ci{ 1143da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 1144da853ecaSopenharmony_ci std::unique_lock<std::mutex> oLock(outputMutex_); 1145da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL, 1146da853ecaSopenharmony_ci "Failed to release output buffer: invalid index"); 1147da853ecaSopenharmony_ci std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index]; 1148da853ecaSopenharmony_ci oLock.unlock(); 1149da853ecaSopenharmony_ci if (frameBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER) { 1150da853ecaSopenharmony_ci frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_CODEC; 1151da853ecaSopenharmony_ci codecAvailQue_->Push(index); 1152da853ecaSopenharmony_ci return AVCS_ERR_OK; 1153da853ecaSopenharmony_ci } else { 1154da853ecaSopenharmony_ci AVCODEC_LOGE("Release output buffer failed: check your index=%{public}u", index); 1155da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 1156da853ecaSopenharmony_ci } 1157da853ecaSopenharmony_ci} 1158da853ecaSopenharmony_ci 1159da853ecaSopenharmony_ciint32_t FCodec::FlushSurfaceMemory(std::shared_ptr<FSurfaceMemory> &surfaceMemory, uint32_t index) 1160da853ecaSopenharmony_ci{ 1161da853ecaSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer(); 1162da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, AVCS_ERR_INVALID_VAL, 1163da853ecaSopenharmony_ci "Failed to update surface memory: surface buffer is NULL"); 1164da853ecaSopenharmony_ci OHOS::BufferFlushConfig flushConfig = {{0, 0, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight()}, 1165da853ecaSopenharmony_ci outAVBuffer4Surface_[index]->pts_, -1}; 1166da853ecaSopenharmony_ci surfaceMemory->SetNeedRender(true); 1167da853ecaSopenharmony_ci surfaceMemory->UpdateSurfaceBufferScaleMode(); 1168da853ecaSopenharmony_ci if (outAVBuffer4Surface_[index]->meta_->Find(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP) != 1169da853ecaSopenharmony_ci outAVBuffer4Surface_[index]->meta_->end()) { 1170da853ecaSopenharmony_ci outAVBuffer4Surface_[index]->meta_->Get<OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP>( 1171da853ecaSopenharmony_ci flushConfig.desiredPresentTimestamp); 1172da853ecaSopenharmony_ci outAVBuffer4Surface_[index]->meta_->Remove(OHOS::Media::Tag::VIDEO_DECODER_DESIRED_PRESENT_TIMESTAMP); 1173da853ecaSopenharmony_ci } 1174da853ecaSopenharmony_ci auto res = sInfo_.surface->FlushBuffer(surfaceBuffer, -1, flushConfig); 1175da853ecaSopenharmony_ci if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) { 1176da853ecaSopenharmony_ci AVCODEC_LOGW("Failed to update surface memory: %{public}d", res); 1177da853ecaSopenharmony_ci surfaceMemory->SetNeedRender(false); 1178da853ecaSopenharmony_ci surfaceMemory->ReleaseSurfaceBuffer(); 1179da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1180da853ecaSopenharmony_ci } 1181da853ecaSopenharmony_ci renderSurfaceBufferMap_[index] = std::make_pair(surfaceBuffer, flushConfig); 1182da853ecaSopenharmony_ci surfaceMemory->ReleaseSurfaceBuffer(); 1183da853ecaSopenharmony_ci return AVCS_ERR_OK; 1184da853ecaSopenharmony_ci} 1185da853ecaSopenharmony_ci 1186da853ecaSopenharmony_ciint32_t FCodec::RenderOutputBuffer(uint32_t index) 1187da853ecaSopenharmony_ci{ 1188da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 1189da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AVCS_ERR_UNSUPPORT, 1190da853ecaSopenharmony_ci "RenderOutputBuffer fail, surface is nullptr"); 1191da853ecaSopenharmony_ci std::unique_lock<std::mutex> oLock(outputMutex_); 1192da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(index < buffers_[INDEX_OUTPUT].size(), AVCS_ERR_INVALID_VAL, 1193da853ecaSopenharmony_ci "Failed to render output buffer: invalid index"); 1194da853ecaSopenharmony_ci std::shared_ptr<FBuffer> frameBuffer = buffers_[INDEX_OUTPUT][index]; 1195da853ecaSopenharmony_ci oLock.unlock(); 1196da853ecaSopenharmony_ci std::lock_guard<std::mutex> sLock(surfaceMutex_); 1197da853ecaSopenharmony_ci if (frameBuffer->owner_ == FBuffer::Owner::OWNED_BY_USER) { 1198da853ecaSopenharmony_ci std::shared_ptr<FSurfaceMemory> surfaceMemory = frameBuffer->sMemory_; 1199da853ecaSopenharmony_ci int32_t ret = FlushSurfaceMemory(surfaceMemory, index); 1200da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 1201da853ecaSopenharmony_ci AVCODEC_LOGW("Update surface memory failed: %{public}d", static_cast<int32_t>(ret)); 1202da853ecaSopenharmony_ci } else { 1203da853ecaSopenharmony_ci AVCODEC_LOGD("Update surface memory successful"); 1204da853ecaSopenharmony_ci } 1205da853ecaSopenharmony_ci frameBuffer->owner_ = FBuffer::Owner::OWNED_BY_SURFACE; 1206da853ecaSopenharmony_ci renderAvailQue_->Push(index); 1207da853ecaSopenharmony_ci AVCODEC_LOGD("render output buffer with index, index=%{public}u", index); 1208da853ecaSopenharmony_ci return AVCS_ERR_OK; 1209da853ecaSopenharmony_ci } else { 1210da853ecaSopenharmony_ci AVCODEC_LOGE("Failed to render output buffer with bad index, index=%{public}u", index); 1211da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 1212da853ecaSopenharmony_ci } 1213da853ecaSopenharmony_ci} 1214da853ecaSopenharmony_ci 1215da853ecaSopenharmony_ciint32_t FCodec::ReplaceOutputSurfaceWhenRunning(sptr<Surface> newSurface) 1216da853ecaSopenharmony_ci{ 1217da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(sInfo_.surface != nullptr, AV_ERR_OPERATE_NOT_PERMIT, 1218da853ecaSopenharmony_ci "Not support convert from AVBuffer Mode to Surface Mode"); 1219da853ecaSopenharmony_ci sptr<Surface> oldSurface = sInfo_.surface; 1220da853ecaSopenharmony_ci uint64_t oldId = oldSurface->GetUniqueId(); 1221da853ecaSopenharmony_ci uint64_t newId = newSurface->GetUniqueId(); 1222da853ecaSopenharmony_ci AVCODEC_LOGI("surface %{public}" PRIu64 " -> %{public}" PRIu64 "", oldId, newId); 1223da853ecaSopenharmony_ci if (oldId == newId) { 1224da853ecaSopenharmony_ci return AVCS_ERR_OK; 1225da853ecaSopenharmony_ci } 1226da853ecaSopenharmony_ci GSError err = RegisterListenerToSurface(newSurface); 1227da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN, 1228da853ecaSopenharmony_ci "surface %{public}" PRIu64 ", RegisterListenerToSurface failed, GSError=%{public}d", newId, err); 1229da853ecaSopenharmony_ci int32_t outputBufferCnt = 0; 1230da853ecaSopenharmony_ci format_.GetIntValue(MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, outputBufferCnt); 1231da853ecaSopenharmony_ci int32_t ret = SetQueueSize(newSurface, outputBufferCnt); 1232da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 1233da853ecaSopenharmony_ci UnRegisterListenerToSurface(newSurface); 1234da853ecaSopenharmony_ci return ret; 1235da853ecaSopenharmony_ci } 1236da853ecaSopenharmony_ci std::unique_lock<std::mutex> sLock(surfaceMutex_); 1237da853ecaSopenharmony_ci ret = SwitchBetweenSurface(newSurface); 1238da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 1239da853ecaSopenharmony_ci UnRegisterListenerToSurface(newSurface); 1240da853ecaSopenharmony_ci sInfo_.surface = oldSurface; 1241da853ecaSopenharmony_ci return ret; 1242da853ecaSopenharmony_ci } 1243da853ecaSopenharmony_ci sLock.unlock(); 1244da853ecaSopenharmony_ci return AVCS_ERR_OK; 1245da853ecaSopenharmony_ci} 1246da853ecaSopenharmony_ci 1247da853ecaSopenharmony_ciint32_t FCodec::SetQueueSize(const sptr<Surface> &surface, uint32_t targetSize) 1248da853ecaSopenharmony_ci{ 1249da853ecaSopenharmony_ci int32_t err = surface->SetQueueSize(targetSize); 1250da853ecaSopenharmony_ci if (err != 0) { 1251da853ecaSopenharmony_ci AVCODEC_LOGE("surface %{public}" PRIu64 ", SetQueueSize to %{public}u failed, GSError=%{public}d", 1252da853ecaSopenharmony_ci surface->GetUniqueId(), targetSize, err); 1253da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1254da853ecaSopenharmony_ci } 1255da853ecaSopenharmony_ci AVCODEC_LOGI("surface %{public}" PRIu64 ", SetQueueSize to %{public}u succ", surface->GetUniqueId(), targetSize); 1256da853ecaSopenharmony_ci return AVCS_ERR_OK; 1257da853ecaSopenharmony_ci} 1258da853ecaSopenharmony_ci 1259da853ecaSopenharmony_ciint32_t FCodec::SwitchBetweenSurface(const sptr<Surface> &newSurface) 1260da853ecaSopenharmony_ci{ 1261da853ecaSopenharmony_ci sptr<Surface> curSurface = sInfo_.surface; 1262da853ecaSopenharmony_ci newSurface->Connect(); // cleancache will work only if the surface is connected by us 1263da853ecaSopenharmony_ci newSurface->CleanCache(); // make sure new surface is empty 1264da853ecaSopenharmony_ci std::vector<uint32_t> ownedBySurfaceBufferIndex; 1265da853ecaSopenharmony_ci uint64_t newId = newSurface->GetUniqueId(); 1266da853ecaSopenharmony_ci for (uint32_t index = 0; index < buffers_[INDEX_OUTPUT].size(); index++) { 1267da853ecaSopenharmony_ci if (buffers_[INDEX_OUTPUT][index]->sMemory_ == nullptr) { 1268da853ecaSopenharmony_ci continue; 1269da853ecaSopenharmony_ci } 1270da853ecaSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = nullptr; 1271da853ecaSopenharmony_ci if (buffers_[INDEX_OUTPUT][index]->owner_ == FBuffer::Owner::OWNED_BY_SURFACE) { 1272da853ecaSopenharmony_ci if (renderSurfaceBufferMap_.count(index)) { 1273da853ecaSopenharmony_ci surfaceBuffer = renderSurfaceBufferMap_[index].first; 1274da853ecaSopenharmony_ci ownedBySurfaceBufferIndex.push_back(index); 1275da853ecaSopenharmony_ci } 1276da853ecaSopenharmony_ci } else { 1277da853ecaSopenharmony_ci surfaceBuffer = buffers_[INDEX_OUTPUT][index]->sMemory_->GetSurfaceBuffer(); 1278da853ecaSopenharmony_ci } 1279da853ecaSopenharmony_ci if (surfaceBuffer == nullptr) { 1280da853ecaSopenharmony_ci AVCODEC_LOGE("Get old surface buffer error!"); 1281da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1282da853ecaSopenharmony_ci } 1283da853ecaSopenharmony_ci int32_t err = newSurface->AttachBufferToQueue(surfaceBuffer); 1284da853ecaSopenharmony_ci if (err != 0) { 1285da853ecaSopenharmony_ci AVCODEC_LOGE("surface %{public}" PRIu64 ", AttachBufferToQueue(seq=%{public}u) failed, GSError=%{public}d", 1286da853ecaSopenharmony_ci newId, surfaceBuffer->GetSeqNum(), err); 1287da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1288da853ecaSopenharmony_ci } 1289da853ecaSopenharmony_ci } 1290da853ecaSopenharmony_ci int32_t videoRotation = 0; 1291da853ecaSopenharmony_ci format_.GetIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, videoRotation); 1292da853ecaSopenharmony_ci sInfo_.surface->SetTransform(TranslateSurfaceRotation(static_cast<VideoRotation>(videoRotation))); 1293da853ecaSopenharmony_ci int32_t scalingMode = 0; 1294da853ecaSopenharmony_ci format_.GetIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, scalingMode); 1295da853ecaSopenharmony_ci sInfo_.scalingMode = static_cast<ScalingMode>(scalingMode); 1296da853ecaSopenharmony_ci sInfo_.surface = newSurface; 1297da853ecaSopenharmony_ci 1298da853ecaSopenharmony_ci for (uint32_t index: ownedBySurfaceBufferIndex) { 1299da853ecaSopenharmony_ci int32_t ret = RenderNewSurfaceWithOldBuffer(newSurface, index); 1300da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 1301da853ecaSopenharmony_ci return ret; 1302da853ecaSopenharmony_ci } 1303da853ecaSopenharmony_ci } 1304da853ecaSopenharmony_ci 1305da853ecaSopenharmony_ci int32_t ret = UnRegisterListenerToSurface(curSurface); 1306da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 1307da853ecaSopenharmony_ci return ret; 1308da853ecaSopenharmony_ci } 1309da853ecaSopenharmony_ci 1310da853ecaSopenharmony_ci curSurface->CleanCache(true); // make sure old surface is empty and go black 1311da853ecaSopenharmony_ci return AVCS_ERR_OK; 1312da853ecaSopenharmony_ci} 1313da853ecaSopenharmony_ci 1314da853ecaSopenharmony_ciint32_t FCodec::RenderNewSurfaceWithOldBuffer(const sptr<Surface> &newSurface, uint32_t index) 1315da853ecaSopenharmony_ci{ 1316da853ecaSopenharmony_ci std::shared_ptr<FSurfaceMemory> surfaceMemory = buffers_[INDEX_OUTPUT][index]->sMemory_; 1317da853ecaSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = renderSurfaceBufferMap_[index].first; 1318da853ecaSopenharmony_ci OHOS::BufferFlushConfig flushConfig = renderSurfaceBufferMap_[index].second; 1319da853ecaSopenharmony_ci surfaceMemory->SetNeedRender(true); 1320da853ecaSopenharmony_ci newSurface->SetScalingMode(surfaceBuffer->GetSeqNum(), sInfo_.scalingMode); 1321da853ecaSopenharmony_ci auto res = newSurface->FlushBuffer(surfaceBuffer, -1, flushConfig); 1322da853ecaSopenharmony_ci if (res != OHOS::SurfaceError::SURFACE_ERROR_OK) { 1323da853ecaSopenharmony_ci AVCODEC_LOGE("Failed to update surface memory: %{public}d", res); 1324da853ecaSopenharmony_ci surfaceMemory->SetNeedRender(false); 1325da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1326da853ecaSopenharmony_ci } 1327da853ecaSopenharmony_ci return AVCS_ERR_OK; 1328da853ecaSopenharmony_ci} 1329da853ecaSopenharmony_ci 1330da853ecaSopenharmony_civoid FCodec::RequestBufferFromConsumer() 1331da853ecaSopenharmony_ci{ 1332da853ecaSopenharmony_ci auto index = renderAvailQue_->Front(); 1333da853ecaSopenharmony_ci std::shared_ptr<FBuffer> outputBuffer = buffers_[INDEX_OUTPUT][index]; 1334da853ecaSopenharmony_ci std::shared_ptr<FSurfaceMemory> surfaceMemory = outputBuffer->sMemory_; 1335da853ecaSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = surfaceMemory->GetSurfaceBuffer(); 1336da853ecaSopenharmony_ci if (surfaceBuffer == nullptr) { 1337da853ecaSopenharmony_ci AVCODEC_LOGE("get buffer failed."); 1338da853ecaSopenharmony_ci return; 1339da853ecaSopenharmony_ci } 1340da853ecaSopenharmony_ci auto queSize = renderAvailQue_->Size(); 1341da853ecaSopenharmony_ci uint32_t curIndex = 0; 1342da853ecaSopenharmony_ci uint32_t i = 0; 1343da853ecaSopenharmony_ci for (i = 0; i < queSize; i++) { 1344da853ecaSopenharmony_ci curIndex = renderAvailQue_->Pop(); 1345da853ecaSopenharmony_ci if (surfaceMemory->GetBase() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetAddr() && 1346da853ecaSopenharmony_ci surfaceMemory->GetSize() == buffers_[INDEX_OUTPUT][curIndex]->avBuffer_->memory_->GetCapacity()) { 1347da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT][index]->sMemory_ = buffers_[INDEX_OUTPUT][curIndex]->sMemory_; 1348da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT][curIndex]->sMemory_ = surfaceMemory; 1349da853ecaSopenharmony_ci break; 1350da853ecaSopenharmony_ci } else { 1351da853ecaSopenharmony_ci renderAvailQue_->Push(curIndex); 1352da853ecaSopenharmony_ci } 1353da853ecaSopenharmony_ci } 1354da853ecaSopenharmony_ci if (i == queSize) { 1355da853ecaSopenharmony_ci curIndex = index; 1356da853ecaSopenharmony_ci outputBuffer->avBuffer_ = AVBuffer::CreateAVBuffer(surfaceMemory->GetBase(), surfaceMemory->GetSize()); 1357da853ecaSopenharmony_ci outputBuffer->width_ = width_; 1358da853ecaSopenharmony_ci outputBuffer->height_ = height_; 1359da853ecaSopenharmony_ci FindAvailIndex(curIndex); 1360da853ecaSopenharmony_ci } 1361da853ecaSopenharmony_ci buffers_[INDEX_OUTPUT][curIndex]->owner_ = FBuffer::Owner::OWNED_BY_CODEC; 1362da853ecaSopenharmony_ci codecAvailQue_->Push(curIndex); 1363da853ecaSopenharmony_ci if (renderSurfaceBufferMap_.count(curIndex)) { 1364da853ecaSopenharmony_ci renderSurfaceBufferMap_.erase(curIndex); 1365da853ecaSopenharmony_ci } 1366da853ecaSopenharmony_ci AVCODEC_LOGD("Request output buffer success, index = %{public}u, queSize=%{public}zu, i=%{public}d", curIndex, 1367da853ecaSopenharmony_ci queSize, i); 1368da853ecaSopenharmony_ci} 1369da853ecaSopenharmony_ci 1370da853ecaSopenharmony_ciGSError FCodec::BufferReleasedByConsumer(uint64_t surfaceId) 1371da853ecaSopenharmony_ci{ 1372da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(state_ == State::RUNNING || state_ == State::EOS, GSERROR_NO_PERMISSION, "In valid state"); 1373da853ecaSopenharmony_ci std::lock_guard<std::mutex> sLock(surfaceMutex_); 1374da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(renderAvailQue_->Size() > 0, GSERROR_NO_BUFFER, "No available buffer"); 1375da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(surfaceId == sInfo_.surface->GetUniqueId(), GSERROR_INVALID_ARGUMENTS, 1376da853ecaSopenharmony_ci "Ignore callback from old surface"); 1377da853ecaSopenharmony_ci RequestBufferFromConsumer(); 1378da853ecaSopenharmony_ci return GSERROR_OK; 1379da853ecaSopenharmony_ci} 1380da853ecaSopenharmony_ci 1381da853ecaSopenharmony_ciint32_t FCodec::UnRegisterListenerToSurface(const sptr<Surface> &surface) 1382da853ecaSopenharmony_ci{ 1383da853ecaSopenharmony_ci GSError err = surface->UnRegisterReleaseListener(); 1384da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN, 1385da853ecaSopenharmony_ci "surface %{public}" PRIu64 ", UnRegisterReleaseListener failed, GSError=%{public}d", 1386da853ecaSopenharmony_ci surface->GetUniqueId(), err); 1387da853ecaSopenharmony_ci return AVCS_ERR_OK; 1388da853ecaSopenharmony_ci} 1389da853ecaSopenharmony_ci 1390da853ecaSopenharmony_ciGSError FCodec::RegisterListenerToSurface(const sptr<Surface> &surface) 1391da853ecaSopenharmony_ci{ 1392da853ecaSopenharmony_ci uint64_t surfaceId = surface->GetUniqueId(); 1393da853ecaSopenharmony_ci wptr<FCodec> wp = this; 1394da853ecaSopenharmony_ci GSError err = surface->RegisterReleaseListener([wp, surfaceId](sptr<SurfaceBuffer> &) { 1395da853ecaSopenharmony_ci sptr<FCodec> codec = wp.promote(); 1396da853ecaSopenharmony_ci if (!codec) { 1397da853ecaSopenharmony_ci AVCODEC_LOGD("decoder is gone"); 1398da853ecaSopenharmony_ci return GSERROR_OK; 1399da853ecaSopenharmony_ci } 1400da853ecaSopenharmony_ci return codec->BufferReleasedByConsumer(surfaceId); 1401da853ecaSopenharmony_ci }); 1402da853ecaSopenharmony_ci return err; 1403da853ecaSopenharmony_ci} 1404da853ecaSopenharmony_ci 1405da853ecaSopenharmony_ciint32_t FCodec::SetOutputSurface(sptr<Surface> surface) 1406da853ecaSopenharmony_ci{ 1407da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 1408da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(state_ != State::UNINITIALIZED, AV_ERR_INVALID_VAL, 1409da853ecaSopenharmony_ci "set output surface fail: not initialized or configured"); 1410da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG((state_ == State::CONFIGURED || state_ == State::FLUSHED || 1411da853ecaSopenharmony_ci state_ == State::RUNNING || state_ == State::EOS), AVCS_ERR_INVALID_STATE, 1412da853ecaSopenharmony_ci "set output surface fail: state %{public}d not support set output surface", 1413da853ecaSopenharmony_ci static_cast<int32_t>(state_.load())); 1414da853ecaSopenharmony_ci if (surface == nullptr || surface->IsConsumer()) { 1415da853ecaSopenharmony_ci AVCODEC_LOGE("Set surface fail"); 1416da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 1417da853ecaSopenharmony_ci } 1418da853ecaSopenharmony_ci if (state_ == State::FLUSHED || state_ == State::RUNNING || state_ == State::EOS) { 1419da853ecaSopenharmony_ci return ReplaceOutputSurfaceWhenRunning(surface); 1420da853ecaSopenharmony_ci } 1421da853ecaSopenharmony_ci sInfo_.surface = surface; 1422da853ecaSopenharmony_ci GSError err = RegisterListenerToSurface(sInfo_.surface); 1423da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(err == GSERROR_OK, AVCS_ERR_UNKNOWN, 1424da853ecaSopenharmony_ci "surface %{public}" PRIu64 ", RegisterListenerToSurface failed, GSError=%{public}d", 1425da853ecaSopenharmony_ci sInfo_.surface->GetUniqueId(), err); 1426da853ecaSopenharmony_ci if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_SCALE_TYPE)) { 1427da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(formatMutex_); 1428da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_SCALE_TYPE, 1429da853ecaSopenharmony_ci static_cast<int32_t>(ScalingMode::SCALING_MODE_SCALE_TO_WINDOW)); 1430da853ecaSopenharmony_ci } 1431da853ecaSopenharmony_ci if (!format_.ContainKey(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE)) { 1432da853ecaSopenharmony_ci std::lock_guard<std::mutex> lock(formatMutex_); 1433da853ecaSopenharmony_ci format_.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, 1434da853ecaSopenharmony_ci static_cast<int32_t>(VideoRotation::VIDEO_ROTATION_0)); 1435da853ecaSopenharmony_ci } 1436da853ecaSopenharmony_ci AVCODEC_LOGI("Set surface success"); 1437da853ecaSopenharmony_ci return AVCS_ERR_OK; 1438da853ecaSopenharmony_ci} 1439da853ecaSopenharmony_ci 1440da853ecaSopenharmony_ciint32_t FCodec::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback) 1441da853ecaSopenharmony_ci{ 1442da853ecaSopenharmony_ci AVCODEC_SYNC_TRACE; 1443da853ecaSopenharmony_ci CHECK_AND_RETURN_RET_LOG(callback != nullptr, AVCS_ERR_INVALID_VAL, "Set callback failed: callback is NULL"); 1444da853ecaSopenharmony_ci callback_ = callback; 1445da853ecaSopenharmony_ci return AVCS_ERR_OK; 1446da853ecaSopenharmony_ci} 1447da853ecaSopenharmony_ci 1448da853ecaSopenharmony_ciint32_t FCodec::GetCodecCapability(std::vector<CapabilityData> &capaArray) 1449da853ecaSopenharmony_ci{ 1450da853ecaSopenharmony_ci for (uint32_t i = 0; i < SUPPORT_VCODEC_NUM; ++i) { 1451da853ecaSopenharmony_ci CapabilityData capsData; 1452da853ecaSopenharmony_ci capsData.codecName = static_cast<std::string>(SUPPORT_VCODEC[i].codecName); 1453da853ecaSopenharmony_ci capsData.mimeType = static_cast<std::string>(SUPPORT_VCODEC[i].mimeType); 1454da853ecaSopenharmony_ci capsData.codecType = SUPPORT_VCODEC[i].isEncoder ? AVCODEC_TYPE_VIDEO_ENCODER : AVCODEC_TYPE_VIDEO_DECODER; 1455da853ecaSopenharmony_ci capsData.isVendor = false; 1456da853ecaSopenharmony_ci capsData.maxInstance = VIDEO_INSTANCE_SIZE; 1457da853ecaSopenharmony_ci capsData.alignment.width = VIDEO_ALIGNMENT_SIZE; 1458da853ecaSopenharmony_ci capsData.alignment.height = VIDEO_ALIGNMENT_SIZE; 1459da853ecaSopenharmony_ci capsData.width.minVal = VIDEO_MIN_SIZE; 1460da853ecaSopenharmony_ci capsData.width.maxVal = VIDEO_MAX_WIDTH_SIZE; 1461da853ecaSopenharmony_ci capsData.height.minVal = VIDEO_MIN_SIZE; 1462da853ecaSopenharmony_ci capsData.height.maxVal = VIDEO_MAX_HEIGHT_SIZE; 1463da853ecaSopenharmony_ci capsData.frameRate.minVal = 0; 1464da853ecaSopenharmony_ci capsData.frameRate.maxVal = VIDEO_FRAMERATE_MAX_SIZE; 1465da853ecaSopenharmony_ci capsData.bitrate.minVal = 1; 1466da853ecaSopenharmony_ci capsData.bitrate.maxVal = VIDEO_BITRATE_MAX_SIZE; 1467da853ecaSopenharmony_ci capsData.blockPerFrame.minVal = 1; 1468da853ecaSopenharmony_ci capsData.blockPerFrame.maxVal = VIDEO_BLOCKPERFRAME_SIZE; 1469da853ecaSopenharmony_ci capsData.blockPerSecond.minVal = 1; 1470da853ecaSopenharmony_ci capsData.blockPerSecond.maxVal = VIDEO_BLOCKPERSEC_SIZE; 1471da853ecaSopenharmony_ci capsData.blockSize.width = VIDEO_ALIGN_SIZE; 1472da853ecaSopenharmony_ci capsData.blockSize.height = VIDEO_ALIGN_SIZE; 1473da853ecaSopenharmony_ci if (SUPPORT_VCODEC[i].isEncoder) { 1474da853ecaSopenharmony_ci capsData.complexity.minVal = 0; 1475da853ecaSopenharmony_ci capsData.complexity.maxVal = 0; 1476da853ecaSopenharmony_ci capsData.encodeQuality.minVal = 0; 1477da853ecaSopenharmony_ci capsData.encodeQuality.maxVal = 0; 1478da853ecaSopenharmony_ci } 1479da853ecaSopenharmony_ci capsData.pixFormat = { 1480da853ecaSopenharmony_ci static_cast<int32_t>(VideoPixelFormat::YUVI420), static_cast<int32_t>(VideoPixelFormat::NV12), 1481da853ecaSopenharmony_ci static_cast<int32_t>(VideoPixelFormat::NV21), static_cast<int32_t>(VideoPixelFormat::RGBA)}; 1482da853ecaSopenharmony_ci capsData.profiles = {static_cast<int32_t>(AVC_PROFILE_BASELINE), static_cast<int32_t>(AVC_PROFILE_MAIN), 1483da853ecaSopenharmony_ci static_cast<int32_t>(AVC_PROFILE_HIGH)}; 1484da853ecaSopenharmony_ci std::vector<int32_t> levels; 1485da853ecaSopenharmony_ci for (int32_t j = 0; j <= static_cast<int32_t>(AVCLevel::AVC_LEVEL_51); ++j) { 1486da853ecaSopenharmony_ci levels.emplace_back(j); 1487da853ecaSopenharmony_ci } 1488da853ecaSopenharmony_ci capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_MAIN), levels)); 1489da853ecaSopenharmony_ci capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_HIGH), levels)); 1490da853ecaSopenharmony_ci capsData.profileLevelsMap.insert(std::make_pair(static_cast<int32_t>(AVC_PROFILE_BASELINE), levels)); 1491da853ecaSopenharmony_ci capaArray.emplace_back(capsData); 1492da853ecaSopenharmony_ci } 1493da853ecaSopenharmony_ci return AVCS_ERR_OK; 1494da853ecaSopenharmony_ci} 1495da853ecaSopenharmony_ci} // namespace Codec 1496da853ecaSopenharmony_ci} // namespace MediaAVCodec 1497da853ecaSopenharmony_ci} // namespace OHOS 1498