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 "hcodec.h" 17da853ecaSopenharmony_ci#include <cassert> 18da853ecaSopenharmony_ci#include <vector> 19da853ecaSopenharmony_ci#include <algorithm> 20da853ecaSopenharmony_ci#include <thread> 21da853ecaSopenharmony_ci#include "syspara/parameters.h" // base/startup/init/interfaces/innerkits/include/ 22da853ecaSopenharmony_ci#include "qos.h" 23da853ecaSopenharmony_ci#include "utils/hdf_base.h" 24da853ecaSopenharmony_ci#include "codec_omx_ext.h" 25da853ecaSopenharmony_ci#include "hcodec_list.h" 26da853ecaSopenharmony_ci#include "hencoder.h" 27da853ecaSopenharmony_ci#include "hdecoder.h" 28da853ecaSopenharmony_ci#include "hitrace_meter.h" 29da853ecaSopenharmony_ci#include "hcodec_log.h" 30da853ecaSopenharmony_ci#include "hcodec_dfx.h" 31da853ecaSopenharmony_ci#include "hcodec_utils.h" 32da853ecaSopenharmony_ci#include "av_hardware_memory.h" 33da853ecaSopenharmony_ci#include "av_hardware_allocator.h" 34da853ecaSopenharmony_ci#include "av_shared_memory_ext.h" 35da853ecaSopenharmony_ci#include "av_shared_allocator.h" 36da853ecaSopenharmony_ci#include "av_surface_memory.h" 37da853ecaSopenharmony_ci#include "av_surface_allocator.h" 38da853ecaSopenharmony_ci 39da853ecaSopenharmony_cinamespace OHOS::MediaAVCodec { 40da853ecaSopenharmony_ciusing namespace std; 41da853ecaSopenharmony_ciusing namespace CodecHDI; 42da853ecaSopenharmony_ciusing namespace Media; 43da853ecaSopenharmony_ci 44da853ecaSopenharmony_cistd::shared_ptr<HCodec> HCodec::Create(const std::string &name) 45da853ecaSopenharmony_ci{ 46da853ecaSopenharmony_ci vector<CodecCompCapability> capList = GetCapList(); 47da853ecaSopenharmony_ci shared_ptr<HCodec> codec; 48da853ecaSopenharmony_ci for (const auto& cap : capList) { 49da853ecaSopenharmony_ci if (cap.compName != name) { 50da853ecaSopenharmony_ci continue; 51da853ecaSopenharmony_ci } 52da853ecaSopenharmony_ci optional<OMX_VIDEO_CODINGTYPE> type = TypeConverter::HdiRoleToOmxCodingType(cap.role); 53da853ecaSopenharmony_ci if (!type) { 54da853ecaSopenharmony_ci LOGE("unsupported role %d", cap.role); 55da853ecaSopenharmony_ci return nullptr; 56da853ecaSopenharmony_ci } 57da853ecaSopenharmony_ci if (cap.type == VIDEO_DECODER) { 58da853ecaSopenharmony_ci codec = make_shared<HDecoder>(cap, type.value()); 59da853ecaSopenharmony_ci } else if (cap.type == VIDEO_ENCODER) { 60da853ecaSopenharmony_ci codec = make_shared<HEncoder>(cap, type.value()); 61da853ecaSopenharmony_ci } 62da853ecaSopenharmony_ci break; 63da853ecaSopenharmony_ci } 64da853ecaSopenharmony_ci if (codec == nullptr) { 65da853ecaSopenharmony_ci LOGE("cannot find %s", name.c_str()); 66da853ecaSopenharmony_ci return nullptr; 67da853ecaSopenharmony_ci } 68da853ecaSopenharmony_ci return codec; 69da853ecaSopenharmony_ci} 70da853ecaSopenharmony_ci 71da853ecaSopenharmony_ciint32_t HCodec::Init(Media::Meta &callerInfo) 72da853ecaSopenharmony_ci{ 73da853ecaSopenharmony_ci if (callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PID, playerCaller_.pid) && 74da853ecaSopenharmony_ci callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PROCESS_NAME, playerCaller_.processName)) { 75da853ecaSopenharmony_ci calledByAvcodec_ = false; 76da853ecaSopenharmony_ci } else if (callerInfo.GetData(Tag::AV_CODEC_CALLER_PID, avcodecCaller_.pid) && 77da853ecaSopenharmony_ci callerInfo.GetData(Tag::AV_CODEC_CALLER_PROCESS_NAME, avcodecCaller_.processName)) { 78da853ecaSopenharmony_ci calledByAvcodec_ = true; 79da853ecaSopenharmony_ci } 80da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::INIT, nullptr); 81da853ecaSopenharmony_ci} 82da853ecaSopenharmony_ci 83da853ecaSopenharmony_civoid HCodec::PrintCaller() 84da853ecaSopenharmony_ci{ 85da853ecaSopenharmony_ci if (calledByAvcodec_) { 86da853ecaSopenharmony_ci HLOGI("[pid %d][%s] -> avcodec", avcodecCaller_.pid, avcodecCaller_.processName.c_str()); 87da853ecaSopenharmony_ci } else { 88da853ecaSopenharmony_ci HLOGI("[pid %d][%s] -> player -> avcodec", playerCaller_.pid, playerCaller_.processName.c_str()); 89da853ecaSopenharmony_ci } 90da853ecaSopenharmony_ci} 91da853ecaSopenharmony_ci 92da853ecaSopenharmony_ciint32_t HCodec::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback) 93da853ecaSopenharmony_ci{ 94da853ecaSopenharmony_ci HLOGI(">>"); 95da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 96da853ecaSopenharmony_ci msg->SetValue("callback", callback); 97da853ecaSopenharmony_ci }; 98da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::SET_CALLBACK, proc); 99da853ecaSopenharmony_ci} 100da853ecaSopenharmony_ci 101da853ecaSopenharmony_ciint32_t HCodec::Configure(const Format &format) 102da853ecaSopenharmony_ci{ 103da853ecaSopenharmony_ci SCOPED_TRACE(); 104da853ecaSopenharmony_ci HLOGI("%s", format.Stringify().c_str()); 105da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 106da853ecaSopenharmony_ci msg->SetValue("format", format); 107da853ecaSopenharmony_ci }; 108da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::CONFIGURE, proc); 109da853ecaSopenharmony_ci} 110da853ecaSopenharmony_ci 111da853ecaSopenharmony_ciint32_t HCodec::SetCustomBuffer(std::shared_ptr<AVBuffer> buffer) 112da853ecaSopenharmony_ci{ 113da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 114da853ecaSopenharmony_ci msg->SetValue("buffer", buffer); 115da853ecaSopenharmony_ci }; 116da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::CONFIGURE_BUFFER, proc); 117da853ecaSopenharmony_ci} 118da853ecaSopenharmony_ci 119da853ecaSopenharmony_ciint32_t HCodec::SetOutputSurface(sptr<Surface> surface) 120da853ecaSopenharmony_ci{ 121da853ecaSopenharmony_ci HLOGI(">>"); 122da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 123da853ecaSopenharmony_ci msg->SetValue("surface", surface); 124da853ecaSopenharmony_ci }; 125da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::SET_OUTPUT_SURFACE, proc); 126da853ecaSopenharmony_ci} 127da853ecaSopenharmony_ci 128da853ecaSopenharmony_ciint32_t HCodec::Start() 129da853ecaSopenharmony_ci{ 130da853ecaSopenharmony_ci SCOPED_TRACE(); 131da853ecaSopenharmony_ci FUNC_TRACKER(); 132da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::START, nullptr); 133da853ecaSopenharmony_ci} 134da853ecaSopenharmony_ci 135da853ecaSopenharmony_ciint32_t HCodec::Stop() 136da853ecaSopenharmony_ci{ 137da853ecaSopenharmony_ci SCOPED_TRACE(); 138da853ecaSopenharmony_ci FUNC_TRACKER(); 139da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::STOP, nullptr); 140da853ecaSopenharmony_ci} 141da853ecaSopenharmony_ci 142da853ecaSopenharmony_ciint32_t HCodec::Flush() 143da853ecaSopenharmony_ci{ 144da853ecaSopenharmony_ci SCOPED_TRACE(); 145da853ecaSopenharmony_ci FUNC_TRACKER(); 146da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::FLUSH, nullptr); 147da853ecaSopenharmony_ci} 148da853ecaSopenharmony_ci 149da853ecaSopenharmony_ciint32_t HCodec::Reset() 150da853ecaSopenharmony_ci{ 151da853ecaSopenharmony_ci SCOPED_TRACE(); 152da853ecaSopenharmony_ci FUNC_TRACKER(); 153da853ecaSopenharmony_ci int32_t ret = Release(); 154da853ecaSopenharmony_ci if (ret == AVCS_ERR_OK) { 155da853ecaSopenharmony_ci ret = DoSyncCall(MsgWhat::INIT, nullptr); 156da853ecaSopenharmony_ci } 157da853ecaSopenharmony_ci return ret; 158da853ecaSopenharmony_ci} 159da853ecaSopenharmony_ci 160da853ecaSopenharmony_ciint32_t HCodec::Release() 161da853ecaSopenharmony_ci{ 162da853ecaSopenharmony_ci SCOPED_TRACE(); 163da853ecaSopenharmony_ci FUNC_TRACKER(); 164da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::RELEASE, nullptr); 165da853ecaSopenharmony_ci} 166da853ecaSopenharmony_ci 167da853ecaSopenharmony_ciint32_t HCodec::NotifyEos() 168da853ecaSopenharmony_ci{ 169da853ecaSopenharmony_ci HLOGI(">>"); 170da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::NOTIFY_EOS, nullptr); 171da853ecaSopenharmony_ci} 172da853ecaSopenharmony_ci 173da853ecaSopenharmony_ciint32_t HCodec::SetParameter(const Format &format) 174da853ecaSopenharmony_ci{ 175da853ecaSopenharmony_ci HLOGI("%s", format.Stringify().c_str()); 176da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 177da853ecaSopenharmony_ci msg->SetValue("params", format); 178da853ecaSopenharmony_ci }; 179da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::SET_PARAMETERS, proc); 180da853ecaSopenharmony_ci} 181da853ecaSopenharmony_ci 182da853ecaSopenharmony_ciint32_t HCodec::GetInputFormat(Format& format) 183da853ecaSopenharmony_ci{ 184da853ecaSopenharmony_ci HLOGI(">>"); 185da853ecaSopenharmony_ci ParamSP reply; 186da853ecaSopenharmony_ci int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_INPUT_FORMAT, nullptr, reply); 187da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 188da853ecaSopenharmony_ci HLOGE("failed to get input format"); 189da853ecaSopenharmony_ci return ret; 190da853ecaSopenharmony_ci } 191da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("format", format), 192da853ecaSopenharmony_ci AVCS_ERR_UNKNOWN, "input format not replied"); 193da853ecaSopenharmony_ci return AVCS_ERR_OK; 194da853ecaSopenharmony_ci} 195da853ecaSopenharmony_ci 196da853ecaSopenharmony_ciint32_t HCodec::GetOutputFormat(Format &format) 197da853ecaSopenharmony_ci{ 198da853ecaSopenharmony_ci ParamSP reply; 199da853ecaSopenharmony_ci int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_OUTPUT_FORMAT, nullptr, reply); 200da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 201da853ecaSopenharmony_ci HLOGE("failed to get output format"); 202da853ecaSopenharmony_ci return ret; 203da853ecaSopenharmony_ci } 204da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("format", format), 205da853ecaSopenharmony_ci AVCS_ERR_UNKNOWN, "output format not replied"); 206da853ecaSopenharmony_ci format.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, caps_.compName); 207da853ecaSopenharmony_ci format.PutIntValue("IS_VENDOR", 1); 208da853ecaSopenharmony_ci return AVCS_ERR_OK; 209da853ecaSopenharmony_ci} 210da853ecaSopenharmony_ci 211da853ecaSopenharmony_cistd::string HCodec::GetHidumperInfo() 212da853ecaSopenharmony_ci{ 213da853ecaSopenharmony_ci HLOGI(">>"); 214da853ecaSopenharmony_ci ParamSP reply; 215da853ecaSopenharmony_ci int32_t ret = DoSyncCallAndGetReply(MsgWhat::GET_HIDUMPER_INFO, nullptr, reply); 216da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 217da853ecaSopenharmony_ci HLOGW("failed to get hidumper info"); 218da853ecaSopenharmony_ci return ""; 219da853ecaSopenharmony_ci } 220da853ecaSopenharmony_ci string info; 221da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("hidumper-info", info), 222da853ecaSopenharmony_ci "", "hidumper info not replied"); 223da853ecaSopenharmony_ci return info; 224da853ecaSopenharmony_ci} 225da853ecaSopenharmony_ci 226da853ecaSopenharmony_cisptr<Surface> HCodec::CreateInputSurface() 227da853ecaSopenharmony_ci{ 228da853ecaSopenharmony_ci HLOGI(">>"); 229da853ecaSopenharmony_ci ParamSP reply; 230da853ecaSopenharmony_ci int32_t ret = DoSyncCallAndGetReply(MsgWhat::CREATE_INPUT_SURFACE, nullptr, reply); 231da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 232da853ecaSopenharmony_ci HLOGE("failed to create input surface"); 233da853ecaSopenharmony_ci return nullptr; 234da853ecaSopenharmony_ci } 235da853ecaSopenharmony_ci sptr<Surface> inputSurface; 236da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(!reply->GetValue("surface", inputSurface), nullptr, "input surface not replied"); 237da853ecaSopenharmony_ci return inputSurface; 238da853ecaSopenharmony_ci} 239da853ecaSopenharmony_ci 240da853ecaSopenharmony_ciint32_t HCodec::SetInputSurface(sptr<Surface> surface) 241da853ecaSopenharmony_ci{ 242da853ecaSopenharmony_ci HLOGI(">>"); 243da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 244da853ecaSopenharmony_ci msg->SetValue("surface", surface); 245da853ecaSopenharmony_ci }; 246da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::SET_INPUT_SURFACE, proc); 247da853ecaSopenharmony_ci} 248da853ecaSopenharmony_ci 249da853ecaSopenharmony_ciint32_t HCodec::SignalRequestIDRFrame() 250da853ecaSopenharmony_ci{ 251da853ecaSopenharmony_ci HLOGI(">>"); 252da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::REQUEST_IDR_FRAME, nullptr); 253da853ecaSopenharmony_ci} 254da853ecaSopenharmony_ci 255da853ecaSopenharmony_ciint32_t HCodec::QueueInputBuffer(uint32_t index) 256da853ecaSopenharmony_ci{ 257da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 258da853ecaSopenharmony_ci msg->SetValue(BUFFER_ID, index); 259da853ecaSopenharmony_ci }; 260da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::QUEUE_INPUT_BUFFER, proc); 261da853ecaSopenharmony_ci} 262da853ecaSopenharmony_ci 263da853ecaSopenharmony_ciint32_t HCodec::RenderOutputBuffer(uint32_t index) 264da853ecaSopenharmony_ci{ 265da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 266da853ecaSopenharmony_ci msg->SetValue(BUFFER_ID, index); 267da853ecaSopenharmony_ci }; 268da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::RENDER_OUTPUT_BUFFER, proc); 269da853ecaSopenharmony_ci} 270da853ecaSopenharmony_ci 271da853ecaSopenharmony_ciint32_t HCodec::ReleaseOutputBuffer(uint32_t index) 272da853ecaSopenharmony_ci{ 273da853ecaSopenharmony_ci std::function<void(ParamSP)> proc = [&](ParamSP msg) { 274da853ecaSopenharmony_ci msg->SetValue(BUFFER_ID, index); 275da853ecaSopenharmony_ci }; 276da853ecaSopenharmony_ci return DoSyncCall(MsgWhat::RELEASE_OUTPUT_BUFFER, proc); 277da853ecaSopenharmony_ci} 278da853ecaSopenharmony_ci/**************************** public functions end ****************************/ 279da853ecaSopenharmony_ci 280da853ecaSopenharmony_ci 281da853ecaSopenharmony_ciHCodec::HCodec(CodecCompCapability caps, OMX_VIDEO_CODINGTYPE codingType, bool isEncoder) 282da853ecaSopenharmony_ci : caps_(caps), codingType_(codingType), isEncoder_(isEncoder) 283da853ecaSopenharmony_ci{ 284da853ecaSopenharmony_ci debugMode_ = HiLogIsLoggable(HCODEC_DOMAIN, HCODEC_TAG, LOG_DEBUG); 285da853ecaSopenharmony_ci string dumpModeStr = OHOS::system::GetParameter("hcodec.dump", "0"); 286da853ecaSopenharmony_ci dumpMode_ = static_cast<DumpMode>(strtoul(dumpModeStr.c_str(), nullptr, 2)); // 2 is binary 287da853ecaSopenharmony_ci LOGI(">> debug mode = %d, dump mode = %s(%lu)", 288da853ecaSopenharmony_ci debugMode_, dumpModeStr.c_str(), dumpMode_); 289da853ecaSopenharmony_ci 290da853ecaSopenharmony_ci string isEncoderStr = isEncoder ? "enc." : "dec."; 291da853ecaSopenharmony_ci switch (static_cast<int>(codingType_)) { 292da853ecaSopenharmony_ci case OMX_VIDEO_CodingAVC: 293da853ecaSopenharmony_ci shortName_ = isEncoderStr + "avc"; 294da853ecaSopenharmony_ci break; 295da853ecaSopenharmony_ci case CODEC_OMX_VIDEO_CodingHEVC: 296da853ecaSopenharmony_ci shortName_ = isEncoderStr + "hevc"; 297da853ecaSopenharmony_ci break; 298da853ecaSopenharmony_ci case CODEC_OMX_VIDEO_CodingVVC: 299da853ecaSopenharmony_ci shortName_ = isEncoderStr + "vvc"; 300da853ecaSopenharmony_ci break; 301da853ecaSopenharmony_ci default: 302da853ecaSopenharmony_ci shortName_ = isEncoderStr; 303da853ecaSopenharmony_ci break; 304da853ecaSopenharmony_ci }; 305da853ecaSopenharmony_ci isSecure_ = IsSecureMode(caps_.compName); 306da853ecaSopenharmony_ci if (isSecure_) { 307da853ecaSopenharmony_ci shortName_ += ".secure"; 308da853ecaSopenharmony_ci } 309da853ecaSopenharmony_ci 310da853ecaSopenharmony_ci uninitializedState_ = make_shared<UninitializedState>(this); 311da853ecaSopenharmony_ci initializedState_ = make_shared<InitializedState>(this); 312da853ecaSopenharmony_ci startingState_ = make_shared<StartingState>(this); 313da853ecaSopenharmony_ci runningState_ = make_shared<RunningState>(this); 314da853ecaSopenharmony_ci outputPortChangedState_ = make_shared<OutputPortChangedState>(this); 315da853ecaSopenharmony_ci stoppingState_ = make_shared<StoppingState>(this); 316da853ecaSopenharmony_ci flushingState_ = make_shared<FlushingState>(this); 317da853ecaSopenharmony_ci StateMachine::ChangeStateTo(uninitializedState_); 318da853ecaSopenharmony_ci} 319da853ecaSopenharmony_ci 320da853ecaSopenharmony_ciHCodec::~HCodec() 321da853ecaSopenharmony_ci{ 322da853ecaSopenharmony_ci HLOGI(">>"); 323da853ecaSopenharmony_ci MsgHandleLoop::Stop(); 324da853ecaSopenharmony_ci ReleaseComponent(); 325da853ecaSopenharmony_ci} 326da853ecaSopenharmony_ci 327da853ecaSopenharmony_ciint32_t HCodec::HdiCallback::EventHandler(CodecEventType event, const EventInfo &info) 328da853ecaSopenharmony_ci{ 329da853ecaSopenharmony_ci LOGI("event = %d, data1 = %u, data2 = %u", event, info.data1, info.data2); 330da853ecaSopenharmony_ci ParamSP msg = make_shared<ParamBundle>(); 331da853ecaSopenharmony_ci msg->SetValue("event", event); 332da853ecaSopenharmony_ci msg->SetValue("data1", info.data1); 333da853ecaSopenharmony_ci msg->SetValue("data2", info.data2); 334da853ecaSopenharmony_ci std::shared_ptr<HCodec> codec = codec_.lock(); 335da853ecaSopenharmony_ci if (codec == nullptr) { 336da853ecaSopenharmony_ci LOGI("HCodec is gone"); 337da853ecaSopenharmony_ci return HDF_SUCCESS; 338da853ecaSopenharmony_ci } 339da853ecaSopenharmony_ci codec->SendAsyncMsg(MsgWhat::CODEC_EVENT, msg); 340da853ecaSopenharmony_ci return HDF_SUCCESS; 341da853ecaSopenharmony_ci} 342da853ecaSopenharmony_ci 343da853ecaSopenharmony_ciint32_t HCodec::HdiCallback::EmptyBufferDone(int64_t appData, const OmxCodecBuffer& buffer) 344da853ecaSopenharmony_ci{ 345da853ecaSopenharmony_ci ParamSP msg = make_shared<ParamBundle>(); 346da853ecaSopenharmony_ci msg->SetValue(BUFFER_ID, buffer.bufferId); 347da853ecaSopenharmony_ci std::shared_ptr<HCodec> codec = codec_.lock(); 348da853ecaSopenharmony_ci if (codec == nullptr) { 349da853ecaSopenharmony_ci LOGI("HCodec is gone"); 350da853ecaSopenharmony_ci return HDF_SUCCESS; 351da853ecaSopenharmony_ci } 352da853ecaSopenharmony_ci codec->SendAsyncMsg(MsgWhat::OMX_EMPTY_BUFFER_DONE, msg); 353da853ecaSopenharmony_ci return HDF_SUCCESS; 354da853ecaSopenharmony_ci} 355da853ecaSopenharmony_ci 356da853ecaSopenharmony_ciint32_t HCodec::HdiCallback::FillBufferDone(int64_t appData, const OmxCodecBuffer& buffer) 357da853ecaSopenharmony_ci{ 358da853ecaSopenharmony_ci ParamSP msg = make_shared<ParamBundle>(); 359da853ecaSopenharmony_ci msg->SetValue("omxBuffer", buffer); 360da853ecaSopenharmony_ci std::shared_ptr<HCodec> codec = codec_.lock(); 361da853ecaSopenharmony_ci if (codec == nullptr) { 362da853ecaSopenharmony_ci LOGI("HCodec is gone"); 363da853ecaSopenharmony_ci return HDF_SUCCESS; 364da853ecaSopenharmony_ci } 365da853ecaSopenharmony_ci codec->SendAsyncMsg(MsgWhat::OMX_FILL_BUFFER_DONE, msg); 366da853ecaSopenharmony_ci return HDF_SUCCESS; 367da853ecaSopenharmony_ci} 368da853ecaSopenharmony_ci 369da853ecaSopenharmony_ciint32_t HCodec::SetFrameRateAdaptiveMode(const Format &format) 370da853ecaSopenharmony_ci{ 371da853ecaSopenharmony_ci if (!format.ContainKey(OHOS::Media::Tag::VIDEO_FRAME_RATE_ADAPTIVE_MODE)) { 372da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 373da853ecaSopenharmony_ci } 374da853ecaSopenharmony_ci 375da853ecaSopenharmony_ci WorkingFrequencyParam param {}; 376da853ecaSopenharmony_ci InitOMXParamExt(param); 377da853ecaSopenharmony_ci if (!GetParameter(OMX_IndexParamWorkingFrequency, param)) { 378da853ecaSopenharmony_ci HLOGW("get working freq param failed"); 379da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 380da853ecaSopenharmony_ci } 381da853ecaSopenharmony_ci if (param.level == 0) { 382da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 383da853ecaSopenharmony_ci } 384da853ecaSopenharmony_ci HLOGI("level cnt is %d, set level to %d", param.level, param.level - 1); 385da853ecaSopenharmony_ci param.level = param.level - 1; 386da853ecaSopenharmony_ci 387da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamWorkingFrequency, param)) { 388da853ecaSopenharmony_ci HLOGW("set working freq param failed"); 389da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 390da853ecaSopenharmony_ci } 391da853ecaSopenharmony_ci return AVCS_ERR_OK; 392da853ecaSopenharmony_ci} 393da853ecaSopenharmony_ci 394da853ecaSopenharmony_ciint32_t HCodec::SetProcessName() 395da853ecaSopenharmony_ci{ 396da853ecaSopenharmony_ci const std::string& processName = calledByAvcodec_ ? avcodecCaller_.processName : playerCaller_.processName; 397da853ecaSopenharmony_ci HLOGI("processName is %s", processName.c_str()); 398da853ecaSopenharmony_ci 399da853ecaSopenharmony_ci ProcessNameParam param {}; 400da853ecaSopenharmony_ci InitOMXParamExt(param); 401da853ecaSopenharmony_ci if (strcpy_s(param.processName, sizeof(param.processName), processName.c_str()) != EOK) { 402da853ecaSopenharmony_ci HLOGW("strcpy failed"); 403da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 404da853ecaSopenharmony_ci } 405da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamProcessName, param)) { 406da853ecaSopenharmony_ci HLOGW("set process name failed"); 407da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 408da853ecaSopenharmony_ci } 409da853ecaSopenharmony_ci return AVCS_ERR_OK; 410da853ecaSopenharmony_ci} 411da853ecaSopenharmony_ci 412da853ecaSopenharmony_ciint32_t HCodec::SetLowLatency(const Format &format) 413da853ecaSopenharmony_ci{ 414da853ecaSopenharmony_ci int32_t enableLowLatency; 415da853ecaSopenharmony_ci if (!format.GetIntValue(OHOS::Media::Tag::VIDEO_ENABLE_LOW_LATENCY, enableLowLatency)) { 416da853ecaSopenharmony_ci return AVCS_ERR_OK; 417da853ecaSopenharmony_ci } 418da853ecaSopenharmony_ci if (!caps_.port.video.isSupportLowLatency) { 419da853ecaSopenharmony_ci HLOGW("platform not support LowLatency"); 420da853ecaSopenharmony_ci return AVCS_ERR_OK; 421da853ecaSopenharmony_ci } 422da853ecaSopenharmony_ci 423da853ecaSopenharmony_ci OMX_CONFIG_BOOLEANTYPE param {}; 424da853ecaSopenharmony_ci InitOMXParam(param); 425da853ecaSopenharmony_ci param.bEnabled = enableLowLatency ? OMX_TRUE : OMX_FALSE; 426da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamLowLatency, param)) { 427da853ecaSopenharmony_ci HLOGW("set low latency failed"); 428da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 429da853ecaSopenharmony_ci } 430da853ecaSopenharmony_ci HLOGI("set low latency succ %d", enableLowLatency); 431da853ecaSopenharmony_ci return AVCS_ERR_OK; 432da853ecaSopenharmony_ci} 433da853ecaSopenharmony_ci 434da853ecaSopenharmony_cibool HCodec::GetPixelFmtFromUser(const Format &format) 435da853ecaSopenharmony_ci{ 436da853ecaSopenharmony_ci optional<PixelFmt> fmt; 437da853ecaSopenharmony_ci VideoPixelFormat innerFmt; 438da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, *(int *)&innerFmt) && 439da853ecaSopenharmony_ci innerFmt != VideoPixelFormat::SURFACE_FORMAT) { 440da853ecaSopenharmony_ci fmt = TypeConverter::InnerFmtToFmt(innerFmt); 441da853ecaSopenharmony_ci } else { 442da853ecaSopenharmony_ci HLOGI("user don't set VideoPixelFormat, use default"); 443da853ecaSopenharmony_ci for (int32_t f : caps_.port.video.supportPixFmts) { 444da853ecaSopenharmony_ci fmt = TypeConverter::GraphicFmtToFmt(static_cast<GraphicPixelFormat>(f)); 445da853ecaSopenharmony_ci if (fmt.has_value()) { 446da853ecaSopenharmony_ci break; 447da853ecaSopenharmony_ci } 448da853ecaSopenharmony_ci } 449da853ecaSopenharmony_ci } 450da853ecaSopenharmony_ci if (!fmt) { 451da853ecaSopenharmony_ci HLOGE("pixel format unspecified"); 452da853ecaSopenharmony_ci return false; 453da853ecaSopenharmony_ci } 454da853ecaSopenharmony_ci configuredFmt_ = fmt.value(); 455da853ecaSopenharmony_ci HLOGI("configured pixel format is %s", configuredFmt_.strFmt.c_str()); 456da853ecaSopenharmony_ci return true; 457da853ecaSopenharmony_ci} 458da853ecaSopenharmony_ci 459da853ecaSopenharmony_cistd::optional<double> HCodec::GetFrameRateFromUser(const Format &format) 460da853ecaSopenharmony_ci{ 461da853ecaSopenharmony_ci double frameRateDouble; 462da853ecaSopenharmony_ci if (format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRateDouble) && frameRateDouble > 0) { 463da853ecaSopenharmony_ci LOGI("user set frame rate %.2f", frameRateDouble); 464da853ecaSopenharmony_ci return frameRateDouble; 465da853ecaSopenharmony_ci } 466da853ecaSopenharmony_ci int frameRateInt; 467da853ecaSopenharmony_ci if (format.GetIntValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRateInt) && frameRateInt > 0) { 468da853ecaSopenharmony_ci LOGI("user set frame rate %d", frameRateInt); 469da853ecaSopenharmony_ci return static_cast<double>(frameRateInt); 470da853ecaSopenharmony_ci } 471da853ecaSopenharmony_ci return nullopt; 472da853ecaSopenharmony_ci} 473da853ecaSopenharmony_ci 474da853ecaSopenharmony_cibool HCodec::CheckBufPixFmt(const sptr<SurfaceBuffer>& buffer) 475da853ecaSopenharmony_ci{ 476da853ecaSopenharmony_ci int32_t dispFmt = buffer->GetFormat(); 477da853ecaSopenharmony_ci const std::vector<int32_t>& supportFmts = caps_.port.video.supportPixFmts; 478da853ecaSopenharmony_ci if (std::find(supportFmts.begin(), supportFmts.end(), dispFmt) == supportFmts.end()) { 479da853ecaSopenharmony_ci LOGE("unsupported buffer pixel format %d", dispFmt); 480da853ecaSopenharmony_ci callback_->OnError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_INPUT_DATA_ERROR); 481da853ecaSopenharmony_ci return false; 482da853ecaSopenharmony_ci } 483da853ecaSopenharmony_ci return true; 484da853ecaSopenharmony_ci} 485da853ecaSopenharmony_ci 486da853ecaSopenharmony_ciint32_t HCodec::SetVideoPortInfo(OMX_DIRTYPE portIndex, const PortInfo& info) 487da853ecaSopenharmony_ci{ 488da853ecaSopenharmony_ci if (info.pixelFmt.has_value()) { 489da853ecaSopenharmony_ci CodecVideoPortFormatParam param; 490da853ecaSopenharmony_ci InitOMXParamExt(param); 491da853ecaSopenharmony_ci param.portIndex = portIndex; 492da853ecaSopenharmony_ci param.codecCompressFormat = info.codingType; 493da853ecaSopenharmony_ci param.codecColorFormat = info.pixelFmt->graphicFmt; 494da853ecaSopenharmony_ci param.framerate = info.frameRate * FRAME_RATE_COEFFICIENT; 495da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexCodecVideoPortFormat, param)) { 496da853ecaSopenharmony_ci HLOGE("set port format failed"); 497da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 498da853ecaSopenharmony_ci } 499da853ecaSopenharmony_ci } 500da853ecaSopenharmony_ci { 501da853ecaSopenharmony_ci OMX_PARAM_PORTDEFINITIONTYPE def; 502da853ecaSopenharmony_ci InitOMXParam(def); 503da853ecaSopenharmony_ci def.nPortIndex = portIndex; 504da853ecaSopenharmony_ci if (!GetParameter(OMX_IndexParamPortDefinition, def)) { 505da853ecaSopenharmony_ci HLOGE("get port definition failed"); 506da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 507da853ecaSopenharmony_ci } 508da853ecaSopenharmony_ci def.format.video.nFrameWidth = info.width; 509da853ecaSopenharmony_ci def.format.video.nFrameHeight = info.height; 510da853ecaSopenharmony_ci def.format.video.eCompressionFormat = info.codingType; 511da853ecaSopenharmony_ci // we dont set eColorFormat here because it has been set by CodecVideoPortFormatParam 512da853ecaSopenharmony_ci def.format.video.xFramerate = info.frameRate * FRAME_RATE_COEFFICIENT; 513da853ecaSopenharmony_ci if (portIndex == OMX_DirInput && info.inputBufSize.has_value()) { 514da853ecaSopenharmony_ci def.nBufferSize = info.inputBufSize.value(); 515da853ecaSopenharmony_ci } 516da853ecaSopenharmony_ci if (!SetParameter(OMX_IndexParamPortDefinition, def)) { 517da853ecaSopenharmony_ci HLOGE("set port definition failed"); 518da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 519da853ecaSopenharmony_ci } 520da853ecaSopenharmony_ci if (portIndex == OMX_DirOutput) { 521da853ecaSopenharmony_ci if (outputFormat_ == nullptr) { 522da853ecaSopenharmony_ci outputFormat_ = make_shared<Format>(); 523da853ecaSopenharmony_ci } 524da853ecaSopenharmony_ci outputFormat_->PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, info.frameRate); 525da853ecaSopenharmony_ci } 526da853ecaSopenharmony_ci } 527da853ecaSopenharmony_ci 528da853ecaSopenharmony_ci return (portIndex == OMX_DirInput) ? UpdateInPortFormat() : UpdateOutPortFormat(); 529da853ecaSopenharmony_ci} 530da853ecaSopenharmony_ci 531da853ecaSopenharmony_civoid HCodec::PrintPortDefinition(const OMX_PARAM_PORTDEFINITIONTYPE& def) 532da853ecaSopenharmony_ci{ 533da853ecaSopenharmony_ci const OMX_VIDEO_PORTDEFINITIONTYPE& video = def.format.video; 534da853ecaSopenharmony_ci HLOGI("----- %s port definition -----", (def.nPortIndex == OMX_DirInput) ? "INPUT" : "OUTPUT"); 535da853ecaSopenharmony_ci HLOGI("bEnabled %d, bPopulated %d", def.bEnabled, def.bPopulated); 536da853ecaSopenharmony_ci HLOGI("nBufferCountActual %u, nBufferSize %u", def.nBufferCountActual, def.nBufferSize); 537da853ecaSopenharmony_ci HLOGI("nFrameWidth x nFrameHeight (%u x %u), framerate %u(%.2f)", 538da853ecaSopenharmony_ci video.nFrameWidth, video.nFrameHeight, video.xFramerate, video.xFramerate / FRAME_RATE_COEFFICIENT); 539da853ecaSopenharmony_ci HLOGI(" nStride x nSliceHeight (%u x %u)", video.nStride, video.nSliceHeight); 540da853ecaSopenharmony_ci HLOGI("eCompressionFormat %d(%#x), eColorFormat %d(%#x)", 541da853ecaSopenharmony_ci video.eCompressionFormat, video.eCompressionFormat, video.eColorFormat, video.eColorFormat); 542da853ecaSopenharmony_ci HLOGI("----------------------------------"); 543da853ecaSopenharmony_ci} 544da853ecaSopenharmony_ci 545da853ecaSopenharmony_ciint32_t HCodec::GetPortDefinition(OMX_DIRTYPE portIndex, OMX_PARAM_PORTDEFINITIONTYPE& def) 546da853ecaSopenharmony_ci{ 547da853ecaSopenharmony_ci InitOMXParam(def); 548da853ecaSopenharmony_ci def.nPortIndex = portIndex; 549da853ecaSopenharmony_ci if (!GetParameter(OMX_IndexParamPortDefinition, def)) { 550da853ecaSopenharmony_ci HLOGE("get %s port definition failed", (portIndex == OMX_DirInput ? "input" : "output")); 551da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 552da853ecaSopenharmony_ci } 553da853ecaSopenharmony_ci if (def.nBufferSize == 0 || def.nBufferSize > MAX_HCODEC_BUFFER_SIZE) { 554da853ecaSopenharmony_ci HLOGE("invalid nBufferSize %u", def.nBufferSize); 555da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 556da853ecaSopenharmony_ci } 557da853ecaSopenharmony_ci return AVCS_ERR_OK; 558da853ecaSopenharmony_ci} 559da853ecaSopenharmony_ci 560da853ecaSopenharmony_ciint32_t HCodec::AllocateAvLinearBuffers(OMX_DIRTYPE portIndex) 561da853ecaSopenharmony_ci{ 562da853ecaSopenharmony_ci SCOPED_TRACE(); 563da853ecaSopenharmony_ci OMX_PARAM_PORTDEFINITIONTYPE def; 564da853ecaSopenharmony_ci int32_t ret = GetPortDefinition(portIndex, def); 565da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 566da853ecaSopenharmony_ci return ret; 567da853ecaSopenharmony_ci } 568da853ecaSopenharmony_ci 569da853ecaSopenharmony_ci SupportBufferType type; 570da853ecaSopenharmony_ci InitOMXParamExt(type); 571da853ecaSopenharmony_ci type.portIndex = portIndex; 572da853ecaSopenharmony_ci if (GetParameter(OMX_IndexParamSupportBufferType, type) && (type.bufferTypes & CODEC_BUFFER_TYPE_DMA_MEM_FD)) { 573da853ecaSopenharmony_ci HLOGI("allocate hardware buffer"); 574da853ecaSopenharmony_ci return AllocateAvHardwareBuffers(portIndex, def); 575da853ecaSopenharmony_ci } else { 576da853ecaSopenharmony_ci HLOGI("allocate shared buffer"); 577da853ecaSopenharmony_ci return AllocateAvSharedBuffers(portIndex, def); 578da853ecaSopenharmony_ci } 579da853ecaSopenharmony_ci} 580da853ecaSopenharmony_ci 581da853ecaSopenharmony_ciint32_t HCodec::AllocateAvHardwareBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def) 582da853ecaSopenharmony_ci{ 583da853ecaSopenharmony_ci SCOPED_TRACE(); 584da853ecaSopenharmony_ci vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 585da853ecaSopenharmony_ci pool.clear(); 586da853ecaSopenharmony_ci for (uint32_t i = 0; i < def.nBufferCountActual; ++i) { 587da853ecaSopenharmony_ci std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 588da853ecaSopenharmony_ci omxBuffer->size = sizeof(OmxCodecBuffer); 589da853ecaSopenharmony_ci omxBuffer->version.version.majorVersion = 1; 590da853ecaSopenharmony_ci omxBuffer->bufferType = CODEC_BUFFER_TYPE_DMA_MEM_FD; 591da853ecaSopenharmony_ci omxBuffer->fd = -1; 592da853ecaSopenharmony_ci omxBuffer->allocLen = def.nBufferSize; 593da853ecaSopenharmony_ci omxBuffer->fenceFd = -1; 594da853ecaSopenharmony_ci shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>(); 595da853ecaSopenharmony_ci int32_t ret = compNode_->AllocateBuffer(portIndex, *omxBuffer, *outBuffer); 596da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 597da853ecaSopenharmony_ci HLOGE("Failed to AllocateBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output")); 598da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 599da853ecaSopenharmony_ci } 600da853ecaSopenharmony_ci MemoryFlag memFlag = MEMORY_READ_WRITE; 601da853ecaSopenharmony_ci std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateHardwareAllocator( 602da853ecaSopenharmony_ci outBuffer->fd, static_cast<int32_t>(def.nBufferSize), memFlag, isSecure_); 603da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateHardwareAllocator failed"); 604da853ecaSopenharmony_ci 605da853ecaSopenharmony_ci std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer( 606da853ecaSopenharmony_ci avAllocator, static_cast<int32_t>(def.nBufferSize)); 607da853ecaSopenharmony_ci if (avBuffer == nullptr || avBuffer->memory_ == nullptr || 608da853ecaSopenharmony_ci avBuffer->memory_->GetCapacity() != static_cast<int32_t>(def.nBufferSize)) { 609da853ecaSopenharmony_ci HLOGE("CreateAVBuffer failed"); 610da853ecaSopenharmony_ci return AVCS_ERR_NO_MEMORY; 611da853ecaSopenharmony_ci } 612da853ecaSopenharmony_ci SetCallerToBuffer(outBuffer->fd); 613da853ecaSopenharmony_ci BufferInfo bufInfo; 614da853ecaSopenharmony_ci bufInfo.isInput = (portIndex == OMX_DirInput) ? true : false; 615da853ecaSopenharmony_ci bufInfo.owner = BufferOwner::OWNED_BY_US; 616da853ecaSopenharmony_ci bufInfo.surfaceBuffer = nullptr; 617da853ecaSopenharmony_ci bufInfo.avBuffer = avBuffer; 618da853ecaSopenharmony_ci bufInfo.omxBuffer = outBuffer; 619da853ecaSopenharmony_ci bufInfo.bufferId = outBuffer->bufferId; 620da853ecaSopenharmony_ci bufInfo.CleanUpUnusedInfo(); 621da853ecaSopenharmony_ci pool.push_back(bufInfo); 622da853ecaSopenharmony_ci } 623da853ecaSopenharmony_ci return AVCS_ERR_OK; 624da853ecaSopenharmony_ci} 625da853ecaSopenharmony_ci 626da853ecaSopenharmony_ciint32_t HCodec::AllocateAvSharedBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def) 627da853ecaSopenharmony_ci{ 628da853ecaSopenharmony_ci SCOPED_TRACE(); 629da853ecaSopenharmony_ci MemoryFlag memFlag = MEMORY_READ_WRITE; 630da853ecaSopenharmony_ci std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateSharedAllocator(memFlag); 631da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateSharedAllocator failed"); 632da853ecaSopenharmony_ci 633da853ecaSopenharmony_ci vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 634da853ecaSopenharmony_ci pool.clear(); 635da853ecaSopenharmony_ci for (uint32_t i = 0; i < def.nBufferCountActual; ++i) { 636da853ecaSopenharmony_ci std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(avAllocator, 637da853ecaSopenharmony_ci static_cast<int32_t>(def.nBufferSize)); 638da853ecaSopenharmony_ci if (avBuffer == nullptr || avBuffer->memory_ == nullptr || 639da853ecaSopenharmony_ci avBuffer->memory_->GetCapacity() != static_cast<int32_t>(def.nBufferSize)) { 640da853ecaSopenharmony_ci HLOGE("CreateAVBuffer failed"); 641da853ecaSopenharmony_ci return AVCS_ERR_NO_MEMORY; 642da853ecaSopenharmony_ci } 643da853ecaSopenharmony_ci std::shared_ptr<OmxCodecBuffer> omxBuffer = std::make_shared<OmxCodecBuffer>(); 644da853ecaSopenharmony_ci omxBuffer->size = sizeof(OmxCodecBuffer); 645da853ecaSopenharmony_ci omxBuffer->version.version.majorVersion = 1; 646da853ecaSopenharmony_ci omxBuffer->bufferType = CODEC_BUFFER_TYPE_AVSHARE_MEM_FD; 647da853ecaSopenharmony_ci omxBuffer->fd = avBuffer->memory_->GetFileDescriptor(); 648da853ecaSopenharmony_ci omxBuffer->allocLen = def.nBufferSize; 649da853ecaSopenharmony_ci omxBuffer->fenceFd = -1; 650da853ecaSopenharmony_ci omxBuffer->type = (portIndex == OMX_DirInput) ? READ_ONLY_TYPE : READ_WRITE_TYPE; 651da853ecaSopenharmony_ci shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>(); 652da853ecaSopenharmony_ci int32_t ret = compNode_->UseBuffer(portIndex, *omxBuffer, *outBuffer); 653da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 654da853ecaSopenharmony_ci HLOGE("Failed to UseBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output")); 655da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 656da853ecaSopenharmony_ci } 657da853ecaSopenharmony_ci BufferInfo bufInfo; 658da853ecaSopenharmony_ci bufInfo.isInput = (portIndex == OMX_DirInput) ? true : false; 659da853ecaSopenharmony_ci bufInfo.owner = BufferOwner::OWNED_BY_US; 660da853ecaSopenharmony_ci bufInfo.surfaceBuffer = nullptr; 661da853ecaSopenharmony_ci bufInfo.avBuffer = avBuffer; 662da853ecaSopenharmony_ci bufInfo.omxBuffer = outBuffer; 663da853ecaSopenharmony_ci bufInfo.bufferId = outBuffer->bufferId; 664da853ecaSopenharmony_ci pool.push_back(bufInfo); 665da853ecaSopenharmony_ci } 666da853ecaSopenharmony_ci return AVCS_ERR_OK; 667da853ecaSopenharmony_ci} 668da853ecaSopenharmony_ci 669da853ecaSopenharmony_ciint32_t HCodec::AllocateAvSurfaceBuffers(OMX_DIRTYPE portIndex) 670da853ecaSopenharmony_ci{ 671da853ecaSopenharmony_ci SCOPED_TRACE(); 672da853ecaSopenharmony_ci OMX_PARAM_PORTDEFINITIONTYPE def; 673da853ecaSopenharmony_ci int32_t ret = GetPortDefinition(portIndex, def); 674da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 675da853ecaSopenharmony_ci return ret; 676da853ecaSopenharmony_ci } 677da853ecaSopenharmony_ci std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateSurfaceAllocator(requestCfg_); 678da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(avAllocator == nullptr, AVCS_ERR_INVALID_VAL, "CreateSurfaceAllocator failed"); 679da853ecaSopenharmony_ci bool needDealWithCache = (requestCfg_.usage & BUFFER_USAGE_MEM_MMZ_CACHE); 680da853ecaSopenharmony_ci 681da853ecaSopenharmony_ci vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 682da853ecaSopenharmony_ci pool.clear(); 683da853ecaSopenharmony_ci for (uint32_t i = 0; i < def.nBufferCountActual; ++i) { 684da853ecaSopenharmony_ci std::shared_ptr<AVBuffer> avBuffer = AVBuffer::CreateAVBuffer(avAllocator, 685da853ecaSopenharmony_ci static_cast<int32_t>(def.nBufferSize)); 686da853ecaSopenharmony_ci if (avBuffer == nullptr || avBuffer->memory_ == nullptr) { 687da853ecaSopenharmony_ci HLOGE("CreateAVBuffer failed"); 688da853ecaSopenharmony_ci return AVCS_ERR_NO_MEMORY; 689da853ecaSopenharmony_ci } 690da853ecaSopenharmony_ci sptr<SurfaceBuffer> surfaceBuffer = avBuffer->memory_->GetSurfaceBuffer(); 691da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(surfaceBuffer == nullptr, AVCS_ERR_INVALID_VAL, "avbuffer has null surfacebuffer"); 692da853ecaSopenharmony_ci shared_ptr<OmxCodecBuffer> omxBuffer = isEncoder_ ? 693da853ecaSopenharmony_ci DynamicSurfaceBufferToOmxBuffer() : SurfaceBufferToOmxBuffer(surfaceBuffer); 694da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL(omxBuffer == nullptr, AVCS_ERR_INVALID_VAL); 695da853ecaSopenharmony_ci shared_ptr<OmxCodecBuffer> outBuffer = make_shared<OmxCodecBuffer>(); 696da853ecaSopenharmony_ci int32_t hdiRet = compNode_->UseBuffer(portIndex, *omxBuffer, *outBuffer); 697da853ecaSopenharmony_ci if (hdiRet != HDF_SUCCESS) { 698da853ecaSopenharmony_ci HLOGE("Failed to UseBuffer on %s port", (portIndex == OMX_DirInput ? "input" : "output")); 699da853ecaSopenharmony_ci return AVCS_ERR_INVALID_VAL; 700da853ecaSopenharmony_ci } 701da853ecaSopenharmony_ci BufferInfo bufInfo; 702da853ecaSopenharmony_ci bufInfo.isInput = (portIndex == OMX_DirInput) ? true : false; 703da853ecaSopenharmony_ci bufInfo.owner = BufferOwner::OWNED_BY_US; 704da853ecaSopenharmony_ci bufInfo.surfaceBuffer = surfaceBuffer; 705da853ecaSopenharmony_ci bufInfo.avBuffer = avBuffer; 706da853ecaSopenharmony_ci bufInfo.omxBuffer = outBuffer; 707da853ecaSopenharmony_ci bufInfo.bufferId = outBuffer->bufferId; 708da853ecaSopenharmony_ci bufInfo.needDealWithCache = needDealWithCache; 709da853ecaSopenharmony_ci pool.push_back(bufInfo); 710da853ecaSopenharmony_ci } 711da853ecaSopenharmony_ci 712da853ecaSopenharmony_ci return AVCS_ERR_OK; 713da853ecaSopenharmony_ci} 714da853ecaSopenharmony_ci 715da853ecaSopenharmony_cishared_ptr<OmxCodecBuffer> HCodec::SurfaceBufferToOmxBuffer(const sptr<SurfaceBuffer>& surfaceBuffer) 716da853ecaSopenharmony_ci{ 717da853ecaSopenharmony_ci BufferHandle* bufferHandle = surfaceBuffer->GetBufferHandle(); 718da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(bufferHandle == nullptr, nullptr, "surfacebuffer has null bufferhandle"); 719da853ecaSopenharmony_ci auto omxBuffer = std::make_shared<OmxCodecBuffer>(); 720da853ecaSopenharmony_ci omxBuffer->size = sizeof(OmxCodecBuffer); 721da853ecaSopenharmony_ci omxBuffer->version.version.majorVersion = 1; 722da853ecaSopenharmony_ci omxBuffer->bufferType = CODEC_BUFFER_TYPE_HANDLE; 723da853ecaSopenharmony_ci omxBuffer->bufferhandle = new NativeBuffer(bufferHandle); 724da853ecaSopenharmony_ci omxBuffer->fd = -1; 725da853ecaSopenharmony_ci omxBuffer->allocLen = surfaceBuffer->GetSize(); 726da853ecaSopenharmony_ci omxBuffer->fenceFd = -1; 727da853ecaSopenharmony_ci return omxBuffer; 728da853ecaSopenharmony_ci} 729da853ecaSopenharmony_ci 730da853ecaSopenharmony_cishared_ptr<OmxCodecBuffer> HCodec::DynamicSurfaceBufferToOmxBuffer() 731da853ecaSopenharmony_ci{ 732da853ecaSopenharmony_ci auto omxBuffer = make_shared<OmxCodecBuffer>(); 733da853ecaSopenharmony_ci omxBuffer->size = sizeof(OmxCodecBuffer); 734da853ecaSopenharmony_ci omxBuffer->version.version.majorVersion = 1; 735da853ecaSopenharmony_ci omxBuffer->bufferType = CODEC_BUFFER_TYPE_DYNAMIC_HANDLE; 736da853ecaSopenharmony_ci omxBuffer->fd = -1; 737da853ecaSopenharmony_ci omxBuffer->allocLen = 0; 738da853ecaSopenharmony_ci omxBuffer->fenceFd = -1; 739da853ecaSopenharmony_ci return omxBuffer; 740da853ecaSopenharmony_ci} 741da853ecaSopenharmony_ci 742da853ecaSopenharmony_ciconst char* HCodec::ToString(BufferOwner owner) 743da853ecaSopenharmony_ci{ 744da853ecaSopenharmony_ci switch (owner) { 745da853ecaSopenharmony_ci case BufferOwner::OWNED_BY_US: 746da853ecaSopenharmony_ci return "us"; 747da853ecaSopenharmony_ci case BufferOwner::OWNED_BY_USER: 748da853ecaSopenharmony_ci return "user"; 749da853ecaSopenharmony_ci case BufferOwner::OWNED_BY_OMX: 750da853ecaSopenharmony_ci return "omx"; 751da853ecaSopenharmony_ci case BufferOwner::OWNED_BY_SURFACE: 752da853ecaSopenharmony_ci return "surface"; 753da853ecaSopenharmony_ci default: 754da853ecaSopenharmony_ci return ""; 755da853ecaSopenharmony_ci } 756da853ecaSopenharmony_ci} 757da853ecaSopenharmony_ci 758da853ecaSopenharmony_civoid HCodec::BufferInfo::CleanUpUnusedInfo() 759da853ecaSopenharmony_ci{ 760da853ecaSopenharmony_ci if (omxBuffer == nullptr || omxBuffer->fd < 0) { 761da853ecaSopenharmony_ci return; 762da853ecaSopenharmony_ci } 763da853ecaSopenharmony_ci if (omxBuffer->fd == 0) { 764da853ecaSopenharmony_ci LOGW("fd of omxbuffer should never be 0"); 765da853ecaSopenharmony_ci } 766da853ecaSopenharmony_ci close(omxBuffer->fd); 767da853ecaSopenharmony_ci omxBuffer->fd = -1; 768da853ecaSopenharmony_ci} 769da853ecaSopenharmony_ci 770da853ecaSopenharmony_civoid HCodec::BufferInfo::BeginCpuAccess() 771da853ecaSopenharmony_ci{ 772da853ecaSopenharmony_ci if (surfaceBuffer && needDealWithCache) { 773da853ecaSopenharmony_ci GSError err = surfaceBuffer->InvalidateCache(); 774da853ecaSopenharmony_ci if (err != GSERROR_OK) { 775da853ecaSopenharmony_ci LOGW("InvalidateCache failed, GSError=%d", err); 776da853ecaSopenharmony_ci } 777da853ecaSopenharmony_ci } 778da853ecaSopenharmony_ci} 779da853ecaSopenharmony_ci 780da853ecaSopenharmony_civoid HCodec::BufferInfo::EndCpuAccess() 781da853ecaSopenharmony_ci{ 782da853ecaSopenharmony_ci if (surfaceBuffer && needDealWithCache) { 783da853ecaSopenharmony_ci GSError err = surfaceBuffer->Map(); 784da853ecaSopenharmony_ci if (err != GSERROR_OK) { 785da853ecaSopenharmony_ci LOGW("Map failed, GSError=%d", err); 786da853ecaSopenharmony_ci return; 787da853ecaSopenharmony_ci } 788da853ecaSopenharmony_ci err = surfaceBuffer->FlushCache(); 789da853ecaSopenharmony_ci if (err != GSERROR_OK) { 790da853ecaSopenharmony_ci LOGW("FlushCache failed, GSError=%d", err); 791da853ecaSopenharmony_ci } 792da853ecaSopenharmony_ci } 793da853ecaSopenharmony_ci} 794da853ecaSopenharmony_ci 795da853ecaSopenharmony_ciHCodec::BufferInfo* HCodec::FindBufferInfoByID(OMX_DIRTYPE portIndex, uint32_t bufferId) 796da853ecaSopenharmony_ci{ 797da853ecaSopenharmony_ci vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 798da853ecaSopenharmony_ci for (BufferInfo &info : pool) { 799da853ecaSopenharmony_ci if (info.bufferId == bufferId) { 800da853ecaSopenharmony_ci return &info; 801da853ecaSopenharmony_ci } 802da853ecaSopenharmony_ci } 803da853ecaSopenharmony_ci HLOGE("unknown buffer id %u", bufferId); 804da853ecaSopenharmony_ci return nullptr; 805da853ecaSopenharmony_ci} 806da853ecaSopenharmony_ci 807da853ecaSopenharmony_cioptional<size_t> HCodec::FindBufferIndexByID(OMX_DIRTYPE portIndex, uint32_t bufferId) 808da853ecaSopenharmony_ci{ 809da853ecaSopenharmony_ci const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 810da853ecaSopenharmony_ci for (size_t i = 0; i < pool.size(); i++) { 811da853ecaSopenharmony_ci if (pool[i].bufferId == bufferId) { 812da853ecaSopenharmony_ci return i; 813da853ecaSopenharmony_ci } 814da853ecaSopenharmony_ci } 815da853ecaSopenharmony_ci HLOGE("unknown buffer id %u", bufferId); 816da853ecaSopenharmony_ci return nullopt; 817da853ecaSopenharmony_ci} 818da853ecaSopenharmony_ci 819da853ecaSopenharmony_ciuint32_t HCodec::UserFlagToOmxFlag(AVCodecBufferFlag userFlag) 820da853ecaSopenharmony_ci{ 821da853ecaSopenharmony_ci uint32_t flags = 0; 822da853ecaSopenharmony_ci if (userFlag & AVCODEC_BUFFER_FLAG_EOS) { 823da853ecaSopenharmony_ci flags |= OMX_BUFFERFLAG_EOS; 824da853ecaSopenharmony_ci HLOGI("got input eos"); 825da853ecaSopenharmony_ci } 826da853ecaSopenharmony_ci if (userFlag & AVCODEC_BUFFER_FLAG_SYNC_FRAME) { 827da853ecaSopenharmony_ci flags |= OMX_BUFFERFLAG_SYNCFRAME; 828da853ecaSopenharmony_ci } 829da853ecaSopenharmony_ci if (userFlag & AVCODEC_BUFFER_FLAG_CODEC_DATA) { 830da853ecaSopenharmony_ci flags |= OMX_BUFFERFLAG_CODECCONFIG; 831da853ecaSopenharmony_ci } 832da853ecaSopenharmony_ci return flags; 833da853ecaSopenharmony_ci} 834da853ecaSopenharmony_ci 835da853ecaSopenharmony_ciAVCodecBufferFlag HCodec::OmxFlagToUserFlag(uint32_t omxFlag) 836da853ecaSopenharmony_ci{ 837da853ecaSopenharmony_ci uint32_t flags = 0; 838da853ecaSopenharmony_ci if (omxFlag & OMX_BUFFERFLAG_EOS) { 839da853ecaSopenharmony_ci flags |= AVCODEC_BUFFER_FLAG_EOS; 840da853ecaSopenharmony_ci HLOGI("got output eos"); 841da853ecaSopenharmony_ci } 842da853ecaSopenharmony_ci if (omxFlag & OMX_BUFFERFLAG_SYNCFRAME) { 843da853ecaSopenharmony_ci flags |= AVCODEC_BUFFER_FLAG_SYNC_FRAME; 844da853ecaSopenharmony_ci } 845da853ecaSopenharmony_ci if (omxFlag & OMX_BUFFERFLAG_CODECCONFIG) { 846da853ecaSopenharmony_ci flags |= AVCODEC_BUFFER_FLAG_CODEC_DATA; 847da853ecaSopenharmony_ci } 848da853ecaSopenharmony_ci return static_cast<AVCodecBufferFlag>(flags); 849da853ecaSopenharmony_ci} 850da853ecaSopenharmony_ci 851da853ecaSopenharmony_cibool HCodec::WaitFence(const sptr<SyncFence>& fence) 852da853ecaSopenharmony_ci{ 853da853ecaSopenharmony_ci if (fence == nullptr || !fence->IsValid()) { 854da853ecaSopenharmony_ci return true; 855da853ecaSopenharmony_ci } 856da853ecaSopenharmony_ci SCOPED_TRACE(); 857da853ecaSopenharmony_ci auto before = chrono::steady_clock::now(); 858da853ecaSopenharmony_ci int waitRes = fence->Wait(WAIT_FENCE_MS); 859da853ecaSopenharmony_ci if (waitRes == 0) { 860da853ecaSopenharmony_ci int64_t costMs = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - before).count(); 861da853ecaSopenharmony_ci if (costMs >= WARN_FENCE_MS) { 862da853ecaSopenharmony_ci HLOGW("wait fence succ but cost %" PRId64 " ms", costMs); 863da853ecaSopenharmony_ci } 864da853ecaSopenharmony_ci return true; 865da853ecaSopenharmony_ci } else { 866da853ecaSopenharmony_ci HLOGE("wait fence time out, cost more than %u ms", WAIT_FENCE_MS); 867da853ecaSopenharmony_ci return false; 868da853ecaSopenharmony_ci } 869da853ecaSopenharmony_ci} 870da853ecaSopenharmony_ci 871da853ecaSopenharmony_civoid HCodec::NotifyUserToFillThisInBuffer(BufferInfo &info) 872da853ecaSopenharmony_ci{ 873da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(info.bufferId); 874da853ecaSopenharmony_ci callback_->OnInputBufferAvailable(info.bufferId, info.avBuffer); 875da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_USER); 876da853ecaSopenharmony_ci} 877da853ecaSopenharmony_ci 878da853ecaSopenharmony_civoid HCodec::OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode) 879da853ecaSopenharmony_ci{ 880da853ecaSopenharmony_ci uint32_t bufferId = 0; 881da853ecaSopenharmony_ci (void)msg.param->GetValue(BUFFER_ID, bufferId); 882da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(bufferId); 883da853ecaSopenharmony_ci BufferInfo* bufferInfo = FindBufferInfoByID(OMX_DirInput, bufferId); 884da853ecaSopenharmony_ci if (bufferInfo == nullptr) { 885da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 886da853ecaSopenharmony_ci return; 887da853ecaSopenharmony_ci } 888da853ecaSopenharmony_ci if (bufferInfo->owner != BufferOwner::OWNED_BY_USER) { 889da853ecaSopenharmony_ci HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(bufferInfo->owner)); 890da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 891da853ecaSopenharmony_ci return; 892da853ecaSopenharmony_ci } 893da853ecaSopenharmony_ci if (!gotFirstInput_) { 894da853ecaSopenharmony_ci HLOGI("got first input"); 895da853ecaSopenharmony_ci gotFirstInput_ = true; 896da853ecaSopenharmony_ci } 897da853ecaSopenharmony_ci bufferInfo->omxBuffer->filledLen = static_cast<uint32_t> 898da853ecaSopenharmony_ci (bufferInfo->avBuffer->memory_->GetSize()); 899da853ecaSopenharmony_ci bufferInfo->omxBuffer->offset = static_cast<uint32_t>(bufferInfo->avBuffer->memory_->GetOffset()); 900da853ecaSopenharmony_ci bufferInfo->omxBuffer->pts = bufferInfo->avBuffer->pts_; 901da853ecaSopenharmony_ci bufferInfo->omxBuffer->flag = UserFlagToOmxFlag(static_cast<AVCodecBufferFlag>(bufferInfo->avBuffer->flag_)); 902da853ecaSopenharmony_ci ChangeOwner(*bufferInfo, BufferOwner::OWNED_BY_US); 903da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_OK); 904da853ecaSopenharmony_ci int32_t ret = OnQueueInputBuffer(mode, bufferInfo); 905da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 906da853ecaSopenharmony_ci SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN); 907da853ecaSopenharmony_ci } 908da853ecaSopenharmony_ci} 909da853ecaSopenharmony_ci 910da853ecaSopenharmony_ciint32_t HCodec::OnQueueInputBuffer(BufferOperationMode mode, BufferInfo* info) 911da853ecaSopenharmony_ci{ 912da853ecaSopenharmony_ci switch (mode) { 913da853ecaSopenharmony_ci case KEEP_BUFFER: { 914da853ecaSopenharmony_ci return AVCS_ERR_OK; 915da853ecaSopenharmony_ci } 916da853ecaSopenharmony_ci case RESUBMIT_BUFFER: { 917da853ecaSopenharmony_ci if (inputPortEos_) { 918da853ecaSopenharmony_ci HLOGI("input already eos, keep this buffer"); 919da853ecaSopenharmony_ci return AVCS_ERR_OK; 920da853ecaSopenharmony_ci } 921da853ecaSopenharmony_ci bool eos = (info->omxBuffer->flag & OMX_BUFFERFLAG_EOS); 922da853ecaSopenharmony_ci if (!eos && info->omxBuffer->filledLen == 0) { 923da853ecaSopenharmony_ci HLOGI("this is not a eos buffer but not filled, ask user to re-fill it"); 924da853ecaSopenharmony_ci NotifyUserToFillThisInBuffer(*info); 925da853ecaSopenharmony_ci return AVCS_ERR_OK; 926da853ecaSopenharmony_ci } 927da853ecaSopenharmony_ci if (eos) { 928da853ecaSopenharmony_ci inputPortEos_ = true; 929da853ecaSopenharmony_ci } 930da853ecaSopenharmony_ci return NotifyOmxToEmptyThisInBuffer(*info); 931da853ecaSopenharmony_ci } 932da853ecaSopenharmony_ci default: { 933da853ecaSopenharmony_ci HLOGE("SHOULD NEVER BE HERE"); 934da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 935da853ecaSopenharmony_ci } 936da853ecaSopenharmony_ci } 937da853ecaSopenharmony_ci} 938da853ecaSopenharmony_ci 939da853ecaSopenharmony_civoid HCodec::WrapSurfaceBufferToSlot(BufferInfo &info, 940da853ecaSopenharmony_ci const sptr<SurfaceBuffer>& surfaceBuffer, int64_t pts, uint32_t flag) 941da853ecaSopenharmony_ci{ 942da853ecaSopenharmony_ci info.surfaceBuffer = surfaceBuffer; 943da853ecaSopenharmony_ci info.omxBuffer->bufferhandle = new NativeBuffer(surfaceBuffer->GetBufferHandle()); 944da853ecaSopenharmony_ci info.omxBuffer->filledLen = surfaceBuffer->GetSize(); 945da853ecaSopenharmony_ci info.omxBuffer->fd = -1; 946da853ecaSopenharmony_ci info.omxBuffer->fenceFd = -1; 947da853ecaSopenharmony_ci info.omxBuffer->pts = pts; 948da853ecaSopenharmony_ci info.omxBuffer->flag = flag; 949da853ecaSopenharmony_ci} 950da853ecaSopenharmony_ci 951da853ecaSopenharmony_civoid HCodec::OnSignalEndOfInputStream(const MsgInfo &msg) 952da853ecaSopenharmony_ci{ 953da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT); 954da853ecaSopenharmony_ci} 955da853ecaSopenharmony_ci 956da853ecaSopenharmony_ciint32_t HCodec::NotifyOmxToEmptyThisInBuffer(BufferInfo& info) 957da853ecaSopenharmony_ci{ 958da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(info.bufferId); 959da853ecaSopenharmony_ci#ifdef BUILD_ENG_VERSION 960da853ecaSopenharmony_ci info.Dump(compUniqueStr_, inTotalCnt_, dumpMode_, isEncoder_); 961da853ecaSopenharmony_ci#endif 962da853ecaSopenharmony_ci info.EndCpuAccess(); 963da853ecaSopenharmony_ci int32_t ret = compNode_->EmptyThisBuffer(*(info.omxBuffer)); 964da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 965da853ecaSopenharmony_ci HLOGE("EmptyThisBuffer failed"); 966da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 967da853ecaSopenharmony_ci } 968da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_OMX); 969da853ecaSopenharmony_ci return AVCS_ERR_OK; 970da853ecaSopenharmony_ci} 971da853ecaSopenharmony_ci 972da853ecaSopenharmony_ciint32_t HCodec::NotifyOmxToFillThisOutBuffer(BufferInfo& info) 973da853ecaSopenharmony_ci{ 974da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(info.bufferId); 975da853ecaSopenharmony_ci info.omxBuffer->flag = 0; 976da853ecaSopenharmony_ci int32_t ret = compNode_->FillThisBuffer(*(info.omxBuffer)); 977da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 978da853ecaSopenharmony_ci HLOGE("outBufId = %u failed", info.bufferId); 979da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 980da853ecaSopenharmony_ci } 981da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_OMX); 982da853ecaSopenharmony_ci return AVCS_ERR_OK; 983da853ecaSopenharmony_ci} 984da853ecaSopenharmony_ci 985da853ecaSopenharmony_civoid HCodec::OnOMXFillBufferDone(const OmxCodecBuffer& omxBuffer, BufferOperationMode mode) 986da853ecaSopenharmony_ci{ 987da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(omxBuffer.bufferId); 988da853ecaSopenharmony_ci optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, omxBuffer.bufferId); 989da853ecaSopenharmony_ci if (!idx.has_value()) { 990da853ecaSopenharmony_ci return; 991da853ecaSopenharmony_ci } 992da853ecaSopenharmony_ci BufferInfo& info = outputBufferPool_[idx.value()]; 993da853ecaSopenharmony_ci if (info.owner != BufferOwner::OWNED_BY_OMX) { 994da853ecaSopenharmony_ci HLOGE("wrong ownership: buffer id=%d, owner=%s", info.bufferId, ToString(info.owner)); 995da853ecaSopenharmony_ci return; 996da853ecaSopenharmony_ci } 997da853ecaSopenharmony_ci info.omxBuffer->offset = omxBuffer.offset; 998da853ecaSopenharmony_ci info.omxBuffer->filledLen = omxBuffer.filledLen; 999da853ecaSopenharmony_ci info.omxBuffer->pts = omxBuffer.pts; 1000da853ecaSopenharmony_ci info.omxBuffer->flag = omxBuffer.flag; 1001da853ecaSopenharmony_ci info.omxBuffer->alongParam = std::move(omxBuffer.alongParam); 1002da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_US); 1003da853ecaSopenharmony_ci OnOMXFillBufferDone(mode, info, idx.value()); 1004da853ecaSopenharmony_ci} 1005da853ecaSopenharmony_ci 1006da853ecaSopenharmony_civoid HCodec::OnOMXFillBufferDone(BufferOperationMode mode, BufferInfo& info, size_t bufferIdx) 1007da853ecaSopenharmony_ci{ 1008da853ecaSopenharmony_ci switch (mode) { 1009da853ecaSopenharmony_ci case KEEP_BUFFER: 1010da853ecaSopenharmony_ci return; 1011da853ecaSopenharmony_ci case RESUBMIT_BUFFER: { 1012da853ecaSopenharmony_ci if (outputPortEos_) { 1013da853ecaSopenharmony_ci HLOGI("output eos, keep this buffer"); 1014da853ecaSopenharmony_ci return; 1015da853ecaSopenharmony_ci } 1016da853ecaSopenharmony_ci bool eos = (info.omxBuffer->flag & OMX_BUFFERFLAG_EOS); 1017da853ecaSopenharmony_ci if (!eos && info.omxBuffer->filledLen == 0) { 1018da853ecaSopenharmony_ci HLOGW("it's not a eos buffer but not filled, ask omx to re-fill it"); 1019da853ecaSopenharmony_ci NotifyOmxToFillThisOutBuffer(info); 1020da853ecaSopenharmony_ci return; 1021da853ecaSopenharmony_ci } 1022da853ecaSopenharmony_ci#ifdef USE_VIDEO_PROCESSING_ENGINE 1023da853ecaSopenharmony_ci if (!isEncoder_ && isVrrEnable_) { 1024da853ecaSopenharmony_ci (void)VrrPrediction(info); 1025da853ecaSopenharmony_ci } 1026da853ecaSopenharmony_ci#endif 1027da853ecaSopenharmony_ci NotifyUserOutBufferAvaliable(info); 1028da853ecaSopenharmony_ci if (eos) { 1029da853ecaSopenharmony_ci outputPortEos_ = true; 1030da853ecaSopenharmony_ci } 1031da853ecaSopenharmony_ci return; 1032da853ecaSopenharmony_ci } 1033da853ecaSopenharmony_ci case FREE_BUFFER: 1034da853ecaSopenharmony_ci EraseBufferFromPool(OMX_DirOutput, bufferIdx); 1035da853ecaSopenharmony_ci return; 1036da853ecaSopenharmony_ci default: 1037da853ecaSopenharmony_ci HLOGE("SHOULD NEVER BE HERE"); 1038da853ecaSopenharmony_ci return; 1039da853ecaSopenharmony_ci } 1040da853ecaSopenharmony_ci} 1041da853ecaSopenharmony_ci 1042da853ecaSopenharmony_civoid HCodec::NotifyUserOutBufferAvaliable(BufferInfo &info) 1043da853ecaSopenharmony_ci{ 1044da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(info.bufferId); 1045da853ecaSopenharmony_ci if (!gotFirstOutput_) { 1046da853ecaSopenharmony_ci HLOGI("got first output"); 1047da853ecaSopenharmony_ci OHOS::QOS::ResetThreadQos(); 1048da853ecaSopenharmony_ci gotFirstOutput_ = true; 1049da853ecaSopenharmony_ci } 1050da853ecaSopenharmony_ci info.BeginCpuAccess(); 1051da853ecaSopenharmony_ci#ifdef BUILD_ENG_VERSION 1052da853ecaSopenharmony_ci info.Dump(compUniqueStr_, outRecord_.totalCnt, dumpMode_, isEncoder_); 1053da853ecaSopenharmony_ci#endif 1054da853ecaSopenharmony_ci shared_ptr<OmxCodecBuffer> omxBuffer = info.omxBuffer; 1055da853ecaSopenharmony_ci info.avBuffer->pts_ = omxBuffer->pts; 1056da853ecaSopenharmony_ci info.avBuffer->flag_ = OmxFlagToUserFlag(omxBuffer->flag); 1057da853ecaSopenharmony_ci if (info.avBuffer->memory_) { 1058da853ecaSopenharmony_ci info.avBuffer->memory_->SetSize(static_cast<int32_t>(omxBuffer->filledLen)); 1059da853ecaSopenharmony_ci info.avBuffer->memory_->SetOffset(static_cast<int32_t>(omxBuffer->offset)); 1060da853ecaSopenharmony_ci } 1061da853ecaSopenharmony_ci ExtractPerFrameParamFromOmxBuffer(omxBuffer, info.avBuffer->meta_); 1062da853ecaSopenharmony_ci callback_->OnOutputBufferAvailable(info.bufferId, info.avBuffer); 1063da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_USER); 1064da853ecaSopenharmony_ci} 1065da853ecaSopenharmony_ci 1066da853ecaSopenharmony_civoid HCodec::OnReleaseOutputBuffer(const MsgInfo &msg, BufferOperationMode mode) 1067da853ecaSopenharmony_ci{ 1068da853ecaSopenharmony_ci uint32_t bufferId = 0; 1069da853ecaSopenharmony_ci (void)msg.param->GetValue(BUFFER_ID, bufferId); 1070da853ecaSopenharmony_ci SCOPED_TRACE_WITH_ID(bufferId); 1071da853ecaSopenharmony_ci optional<size_t> idx = FindBufferIndexByID(OMX_DirOutput, bufferId); 1072da853ecaSopenharmony_ci if (!idx.has_value()) { 1073da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1074da853ecaSopenharmony_ci return; 1075da853ecaSopenharmony_ci } 1076da853ecaSopenharmony_ci BufferInfo& info = outputBufferPool_[idx.value()]; 1077da853ecaSopenharmony_ci if (info.owner != BufferOwner::OWNED_BY_USER) { 1078da853ecaSopenharmony_ci HLOGE("wrong ownership: buffer id=%d, owner=%s", bufferId, ToString(info.owner)); 1079da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_INVALID_VAL); 1080da853ecaSopenharmony_ci return; 1081da853ecaSopenharmony_ci } 1082da853ecaSopenharmony_ci OnReleaseOutputBuffer(info); 1083da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_US); 1084da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_OK); 1085da853ecaSopenharmony_ci 1086da853ecaSopenharmony_ci switch (mode) { 1087da853ecaSopenharmony_ci case KEEP_BUFFER: { 1088da853ecaSopenharmony_ci return; 1089da853ecaSopenharmony_ci } 1090da853ecaSopenharmony_ci case RESUBMIT_BUFFER: { 1091da853ecaSopenharmony_ci if (outputPortEos_) { 1092da853ecaSopenharmony_ci HLOGI("output eos, keep this buffer"); 1093da853ecaSopenharmony_ci return; 1094da853ecaSopenharmony_ci } 1095da853ecaSopenharmony_ci int32_t ret = NotifyOmxToFillThisOutBuffer(info); 1096da853ecaSopenharmony_ci if (ret != AVCS_ERR_OK) { 1097da853ecaSopenharmony_ci SignalError(AVCODEC_ERROR_INTERNAL, AVCS_ERR_UNKNOWN); 1098da853ecaSopenharmony_ci } 1099da853ecaSopenharmony_ci return; 1100da853ecaSopenharmony_ci } 1101da853ecaSopenharmony_ci case FREE_BUFFER: { 1102da853ecaSopenharmony_ci EraseBufferFromPool(OMX_DirOutput, idx.value()); 1103da853ecaSopenharmony_ci return; 1104da853ecaSopenharmony_ci } 1105da853ecaSopenharmony_ci default: { 1106da853ecaSopenharmony_ci HLOGE("SHOULD NEVER BE HERE"); 1107da853ecaSopenharmony_ci return; 1108da853ecaSopenharmony_ci } 1109da853ecaSopenharmony_ci } 1110da853ecaSopenharmony_ci} 1111da853ecaSopenharmony_ci 1112da853ecaSopenharmony_civoid HCodec::OnRenderOutputBuffer(const MsgInfo &msg, BufferOperationMode mode) 1113da853ecaSopenharmony_ci{ 1114da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT); 1115da853ecaSopenharmony_ci} 1116da853ecaSopenharmony_ci 1117da853ecaSopenharmony_civoid HCodec::ReclaimBuffer(OMX_DIRTYPE portIndex, BufferOwner owner, bool erase) 1118da853ecaSopenharmony_ci{ 1119da853ecaSopenharmony_ci vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 1120da853ecaSopenharmony_ci for (size_t i = pool.size(); i > 0;) { 1121da853ecaSopenharmony_ci i--; 1122da853ecaSopenharmony_ci BufferInfo& info = pool[i]; 1123da853ecaSopenharmony_ci if (info.owner == owner) { 1124da853ecaSopenharmony_ci ChangeOwner(info, BufferOwner::OWNED_BY_US); 1125da853ecaSopenharmony_ci if (erase) { 1126da853ecaSopenharmony_ci EraseBufferFromPool(portIndex, i); 1127da853ecaSopenharmony_ci } 1128da853ecaSopenharmony_ci } 1129da853ecaSopenharmony_ci } 1130da853ecaSopenharmony_ci} 1131da853ecaSopenharmony_ci 1132da853ecaSopenharmony_cibool HCodec::IsAllBufferOwnedByUsOrSurface(OMX_DIRTYPE portIndex) 1133da853ecaSopenharmony_ci{ 1134da853ecaSopenharmony_ci const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 1135da853ecaSopenharmony_ci for (const BufferInfo& info : pool) { 1136da853ecaSopenharmony_ci if (info.owner != BufferOwner::OWNED_BY_US && 1137da853ecaSopenharmony_ci info.owner != BufferOwner::OWNED_BY_SURFACE) { 1138da853ecaSopenharmony_ci return false; 1139da853ecaSopenharmony_ci } 1140da853ecaSopenharmony_ci } 1141da853ecaSopenharmony_ci return true; 1142da853ecaSopenharmony_ci} 1143da853ecaSopenharmony_ci 1144da853ecaSopenharmony_cibool HCodec::IsAllBufferOwnedByUsOrSurface() 1145da853ecaSopenharmony_ci{ 1146da853ecaSopenharmony_ci return IsAllBufferOwnedByUsOrSurface(OMX_DirInput) && 1147da853ecaSopenharmony_ci IsAllBufferOwnedByUsOrSurface(OMX_DirOutput); 1148da853ecaSopenharmony_ci} 1149da853ecaSopenharmony_ci 1150da853ecaSopenharmony_civoid HCodec::ClearBufferPool(OMX_DIRTYPE portIndex) 1151da853ecaSopenharmony_ci{ 1152da853ecaSopenharmony_ci const vector<BufferInfo>& pool = (portIndex == OMX_DirInput) ? inputBufferPool_ : outputBufferPool_; 1153da853ecaSopenharmony_ci for (size_t i = pool.size(); i > 0;) { 1154da853ecaSopenharmony_ci i--; 1155da853ecaSopenharmony_ci EraseBufferFromPool(portIndex, i); 1156da853ecaSopenharmony_ci } 1157da853ecaSopenharmony_ci OnClearBufferPool(portIndex); 1158da853ecaSopenharmony_ci} 1159da853ecaSopenharmony_ci 1160da853ecaSopenharmony_civoid HCodec::FreeOmxBuffer(OMX_DIRTYPE portIndex, const BufferInfo& info) 1161da853ecaSopenharmony_ci{ 1162da853ecaSopenharmony_ci if (compNode_ && info.omxBuffer) { 1163da853ecaSopenharmony_ci int32_t omxRet = compNode_->FreeBuffer(portIndex, *(info.omxBuffer)); 1164da853ecaSopenharmony_ci if (omxRet != HDF_SUCCESS) { 1165da853ecaSopenharmony_ci HLOGW("notify omx to free buffer failed"); 1166da853ecaSopenharmony_ci } 1167da853ecaSopenharmony_ci } 1168da853ecaSopenharmony_ci} 1169da853ecaSopenharmony_ci 1170da853ecaSopenharmony_civoid HCodec::EraseOutBuffersOwnedByUsOrSurface() 1171da853ecaSopenharmony_ci{ 1172da853ecaSopenharmony_ci // traverse index in reverse order because we need to erase index from vector 1173da853ecaSopenharmony_ci for (size_t i = outputBufferPool_.size(); i > 0;) { 1174da853ecaSopenharmony_ci i--; 1175da853ecaSopenharmony_ci const BufferInfo& info = outputBufferPool_[i]; 1176da853ecaSopenharmony_ci if (info.owner == BufferOwner::OWNED_BY_US || info.owner == BufferOwner::OWNED_BY_SURFACE) { 1177da853ecaSopenharmony_ci EraseBufferFromPool(OMX_DirOutput, i); 1178da853ecaSopenharmony_ci } 1179da853ecaSopenharmony_ci } 1180da853ecaSopenharmony_ci} 1181da853ecaSopenharmony_ci 1182da853ecaSopenharmony_civoid HCodec::OnSetOutputSurface(const MsgInfo &msg, BufferOperationMode mode) 1183da853ecaSopenharmony_ci{ 1184da853ecaSopenharmony_ci (void)msg; 1185da853ecaSopenharmony_ci (void)mode; 1186da853ecaSopenharmony_ci ReplyErrorCode(msg.id, AVCS_ERR_UNSUPPORT); 1187da853ecaSopenharmony_ci} 1188da853ecaSopenharmony_ci 1189da853ecaSopenharmony_ciint32_t HCodec::ForceShutdown(int32_t generation, bool isNeedNotifyCaller) 1190da853ecaSopenharmony_ci{ 1191da853ecaSopenharmony_ci if (generation != stateGeneration_) { 1192da853ecaSopenharmony_ci HLOGE("ignoring stale force shutdown message: #%d (now #%d)", 1193da853ecaSopenharmony_ci generation, stateGeneration_); 1194da853ecaSopenharmony_ci return AVCS_ERR_OK; 1195da853ecaSopenharmony_ci } 1196da853ecaSopenharmony_ci HLOGI("force to shutdown"); 1197da853ecaSopenharmony_ci isShutDownFromRunning_ = true; 1198da853ecaSopenharmony_ci notifyCallerAfterShutdownComplete_ = isNeedNotifyCaller; 1199da853ecaSopenharmony_ci keepComponentAllocated_ = false; 1200da853ecaSopenharmony_ci auto err = compNode_->SendCommand(CODEC_COMMAND_STATE_SET, CODEC_STATE_IDLE, {}); 1201da853ecaSopenharmony_ci if (err == HDF_SUCCESS) { 1202da853ecaSopenharmony_ci ChangeStateTo(stoppingState_); 1203da853ecaSopenharmony_ci } 1204da853ecaSopenharmony_ci return AVCS_ERR_OK; 1205da853ecaSopenharmony_ci} 1206da853ecaSopenharmony_ci 1207da853ecaSopenharmony_civoid HCodec::SignalError(AVCodecErrorType errorType, int32_t errorCode) 1208da853ecaSopenharmony_ci{ 1209da853ecaSopenharmony_ci HLOGE("fatal error happened: errType=%d, errCode=%d", errorType, errorCode); 1210da853ecaSopenharmony_ci hasFatalError_ = true; 1211da853ecaSopenharmony_ci callback_->OnError(errorType, errorCode); 1212da853ecaSopenharmony_ci} 1213da853ecaSopenharmony_ci 1214da853ecaSopenharmony_ciint32_t HCodec::DoSyncCall(MsgWhat msgType, std::function<void(ParamSP)> oper) 1215da853ecaSopenharmony_ci{ 1216da853ecaSopenharmony_ci ParamSP reply; 1217da853ecaSopenharmony_ci return DoSyncCallAndGetReply(msgType, oper, reply); 1218da853ecaSopenharmony_ci} 1219da853ecaSopenharmony_ci 1220da853ecaSopenharmony_ciint32_t HCodec::DoSyncCallAndGetReply(MsgWhat msgType, std::function<void(ParamSP)> oper, ParamSP &reply) 1221da853ecaSopenharmony_ci{ 1222da853ecaSopenharmony_ci ParamSP msg = make_shared<ParamBundle>(); 1223da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(msg == nullptr, AVCS_ERR_NO_MEMORY, "out of memory"); 1224da853ecaSopenharmony_ci if (oper) { 1225da853ecaSopenharmony_ci oper(msg); 1226da853ecaSopenharmony_ci } 1227da853ecaSopenharmony_ci bool ret = MsgHandleLoop::SendSyncMsg(msgType, msg, reply, FIVE_SECONDS_IN_MS); 1228da853ecaSopenharmony_ci if (!ret) { 1229da853ecaSopenharmony_ci HLOGE("wait msg %d(%s) time out", msgType, ToString(msgType)); 1230da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1231da853ecaSopenharmony_ci } 1232da853ecaSopenharmony_ci int32_t err; 1233da853ecaSopenharmony_ci IF_TRUE_RETURN_VAL_WITH_MSG(reply == nullptr || !reply->GetValue("err", err), 1234da853ecaSopenharmony_ci AVCS_ERR_UNKNOWN, "error code of msg %d not replied", msgType); 1235da853ecaSopenharmony_ci return err; 1236da853ecaSopenharmony_ci} 1237da853ecaSopenharmony_ci 1238da853ecaSopenharmony_civoid HCodec::DeferMessage(const MsgInfo &info) 1239da853ecaSopenharmony_ci{ 1240da853ecaSopenharmony_ci deferredQueue_.push_back(info); 1241da853ecaSopenharmony_ci} 1242da853ecaSopenharmony_ci 1243da853ecaSopenharmony_civoid HCodec::ProcessDeferredMessages() 1244da853ecaSopenharmony_ci{ 1245da853ecaSopenharmony_ci for (const MsgInfo &info : deferredQueue_) { 1246da853ecaSopenharmony_ci StateMachine::OnMsgReceived(info); 1247da853ecaSopenharmony_ci } 1248da853ecaSopenharmony_ci deferredQueue_.clear(); 1249da853ecaSopenharmony_ci} 1250da853ecaSopenharmony_ci 1251da853ecaSopenharmony_civoid HCodec::ReplyToSyncMsgLater(const MsgInfo& msg) 1252da853ecaSopenharmony_ci{ 1253da853ecaSopenharmony_ci syncMsgToReply_[msg.type].push(std::make_pair(msg.id, msg.param)); 1254da853ecaSopenharmony_ci} 1255da853ecaSopenharmony_ci 1256da853ecaSopenharmony_cibool HCodec::GetFirstSyncMsgToReply(MsgInfo& msg) 1257da853ecaSopenharmony_ci{ 1258da853ecaSopenharmony_ci auto iter = syncMsgToReply_.find(msg.type); 1259da853ecaSopenharmony_ci if (iter == syncMsgToReply_.end()) { 1260da853ecaSopenharmony_ci return false; 1261da853ecaSopenharmony_ci } 1262da853ecaSopenharmony_ci std::tie(msg.id, msg.param) = iter->second.front(); 1263da853ecaSopenharmony_ci iter->second.pop(); 1264da853ecaSopenharmony_ci return true; 1265da853ecaSopenharmony_ci} 1266da853ecaSopenharmony_ci 1267da853ecaSopenharmony_civoid HCodec::ReplyErrorCode(MsgId id, int32_t err) 1268da853ecaSopenharmony_ci{ 1269da853ecaSopenharmony_ci if (id == ASYNC_MSG_ID) { 1270da853ecaSopenharmony_ci return; 1271da853ecaSopenharmony_ci } 1272da853ecaSopenharmony_ci ParamSP reply = make_shared<ParamBundle>(); 1273da853ecaSopenharmony_ci reply->SetValue("err", err); 1274da853ecaSopenharmony_ci PostReply(id, reply); 1275da853ecaSopenharmony_ci} 1276da853ecaSopenharmony_ci 1277da853ecaSopenharmony_civoid HCodec::ChangeOmxToTargetState(CodecStateType &state, CodecStateType targetState) 1278da853ecaSopenharmony_ci{ 1279da853ecaSopenharmony_ci int32_t ret = compNode_->SendCommand(CODEC_COMMAND_STATE_SET, targetState, {}); 1280da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 1281da853ecaSopenharmony_ci HLOGE("failed to change omx state, ret=%d", ret); 1282da853ecaSopenharmony_ci return; 1283da853ecaSopenharmony_ci } 1284da853ecaSopenharmony_ci 1285da853ecaSopenharmony_ci int tryCnt = 0; 1286da853ecaSopenharmony_ci do { 1287da853ecaSopenharmony_ci if (tryCnt++ > 10) { // try up to 10 times 1288da853ecaSopenharmony_ci HLOGE("failed to change to state(%d), abort", targetState); 1289da853ecaSopenharmony_ci state = CODEC_STATE_INVALID; 1290da853ecaSopenharmony_ci break; 1291da853ecaSopenharmony_ci } 1292da853ecaSopenharmony_ci this_thread::sleep_for(10ms); // wait 10ms 1293da853ecaSopenharmony_ci ret = compNode_->GetState(state); 1294da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 1295da853ecaSopenharmony_ci HLOGE("failed to get omx state, ret=%d", ret); 1296da853ecaSopenharmony_ci } 1297da853ecaSopenharmony_ci } while (ret == HDF_SUCCESS && state != targetState && state != CODEC_STATE_INVALID); 1298da853ecaSopenharmony_ci} 1299da853ecaSopenharmony_ci 1300da853ecaSopenharmony_cibool HCodec::RollOmxBackToLoaded() 1301da853ecaSopenharmony_ci{ 1302da853ecaSopenharmony_ci CodecStateType state; 1303da853ecaSopenharmony_ci int32_t ret = compNode_->GetState(state); 1304da853ecaSopenharmony_ci if (ret != HDF_SUCCESS) { 1305da853ecaSopenharmony_ci HLOGE("failed to get omx node status(ret=%d), can not perform state rollback", ret); 1306da853ecaSopenharmony_ci return false; 1307da853ecaSopenharmony_ci } 1308da853ecaSopenharmony_ci HLOGI("current omx state (%d)", state); 1309da853ecaSopenharmony_ci switch (state) { 1310da853ecaSopenharmony_ci case CODEC_STATE_EXECUTING: { 1311da853ecaSopenharmony_ci ChangeOmxToTargetState(state, CODEC_STATE_IDLE); 1312da853ecaSopenharmony_ci [[fallthrough]]; 1313da853ecaSopenharmony_ci } 1314da853ecaSopenharmony_ci case CODEC_STATE_IDLE: { 1315da853ecaSopenharmony_ci ChangeOmxToTargetState(state, CODEC_STATE_LOADED); 1316da853ecaSopenharmony_ci [[fallthrough]]; 1317da853ecaSopenharmony_ci } 1318da853ecaSopenharmony_ci case CODEC_STATE_LOADED: 1319da853ecaSopenharmony_ci case CODEC_STATE_INVALID: { 1320da853ecaSopenharmony_ci return true; 1321da853ecaSopenharmony_ci } 1322da853ecaSopenharmony_ci default: { 1323da853ecaSopenharmony_ci HLOGE("invalid omx state: %d", state); 1324da853ecaSopenharmony_ci return false; 1325da853ecaSopenharmony_ci } 1326da853ecaSopenharmony_ci } 1327da853ecaSopenharmony_ci} 1328da853ecaSopenharmony_ci 1329da853ecaSopenharmony_civoid HCodec::CleanUpOmxNode() 1330da853ecaSopenharmony_ci{ 1331da853ecaSopenharmony_ci if (compNode_ == nullptr) { 1332da853ecaSopenharmony_ci return; 1333da853ecaSopenharmony_ci } 1334da853ecaSopenharmony_ci 1335da853ecaSopenharmony_ci if (RollOmxBackToLoaded()) { 1336da853ecaSopenharmony_ci for (const BufferInfo& info : inputBufferPool_) { 1337da853ecaSopenharmony_ci FreeOmxBuffer(OMX_DirInput, info); 1338da853ecaSopenharmony_ci } 1339da853ecaSopenharmony_ci for (const BufferInfo& info : outputBufferPool_) { 1340da853ecaSopenharmony_ci FreeOmxBuffer(OMX_DirOutput, info); 1341da853ecaSopenharmony_ci } 1342da853ecaSopenharmony_ci } 1343da853ecaSopenharmony_ci} 1344da853ecaSopenharmony_ci 1345da853ecaSopenharmony_ciint32_t HCodec::OnAllocateComponent() 1346da853ecaSopenharmony_ci{ 1347da853ecaSopenharmony_ci HitraceScoped trace(HITRACE_TAG_ZMEDIA, "hcodec_AllocateComponent_" + caps_.compName); 1348da853ecaSopenharmony_ci compMgr_ = GetManager(false, caps_.port.video.isSupportPassthrough, isSecure_); 1349da853ecaSopenharmony_ci if (compMgr_ == nullptr) { 1350da853ecaSopenharmony_ci HLOGE("GetCodecComponentManager failed"); 1351da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1352da853ecaSopenharmony_ci } 1353da853ecaSopenharmony_ci compCb_ = new HdiCallback(weak_from_this()); 1354da853ecaSopenharmony_ci int32_t ret = compMgr_->CreateComponent(compNode_, componentId_, caps_.compName, 0, compCb_); 1355da853ecaSopenharmony_ci if (ret != HDF_SUCCESS || compNode_ == nullptr) { 1356da853ecaSopenharmony_ci compCb_ = nullptr; 1357da853ecaSopenharmony_ci compMgr_ = nullptr; 1358da853ecaSopenharmony_ci HLOGE("CreateComponent failed, ret=%d", ret); 1359da853ecaSopenharmony_ci return AVCS_ERR_UNKNOWN; 1360da853ecaSopenharmony_ci } 1361da853ecaSopenharmony_ci compUniqueStr_ = "[" + to_string(componentId_) + "][" + shortName_ + "]"; 1362da853ecaSopenharmony_ci inputOwnerStr_ = { compUniqueStr_ + "in_us", compUniqueStr_ + "in_user", 1363da853ecaSopenharmony_ci compUniqueStr_ + "in_omx", compUniqueStr_ + "in_surface"}; 1364da853ecaSopenharmony_ci outputOwnerStr_ = { compUniqueStr_ + "out_us", compUniqueStr_ + "out_user", 1365da853ecaSopenharmony_ci compUniqueStr_ + "out_omx", compUniqueStr_ + "out_surface"}; 1366da853ecaSopenharmony_ci HLOGI("create omx node %s succ", caps_.compName.c_str()); 1367da853ecaSopenharmony_ci PrintCaller(); 1368da853ecaSopenharmony_ci return AVCS_ERR_OK; 1369da853ecaSopenharmony_ci} 1370da853ecaSopenharmony_ci 1371da853ecaSopenharmony_civoid HCodec::ReleaseComponent() 1372da853ecaSopenharmony_ci{ 1373da853ecaSopenharmony_ci CleanUpOmxNode(); 1374da853ecaSopenharmony_ci if (compMgr_ != nullptr) { 1375da853ecaSopenharmony_ci compMgr_->DestroyComponent(componentId_); 1376da853ecaSopenharmony_ci } 1377da853ecaSopenharmony_ci compNode_ = nullptr; 1378da853ecaSopenharmony_ci compCb_ = nullptr; 1379da853ecaSopenharmony_ci compMgr_ = nullptr; 1380da853ecaSopenharmony_ci componentId_ = 0; 1381da853ecaSopenharmony_ci} 1382da853ecaSopenharmony_ci 1383da853ecaSopenharmony_ciconst char* HCodec::ToString(MsgWhat what) 1384da853ecaSopenharmony_ci{ 1385da853ecaSopenharmony_ci static const map<MsgWhat, const char*> m = { 1386da853ecaSopenharmony_ci { INIT, "INIT" }, { SET_CALLBACK, "SET_CALLBACK" }, { CONFIGURE, "CONFIGURE" }, 1387da853ecaSopenharmony_ci { CREATE_INPUT_SURFACE, "CREATE_INPUT_SURFACE" }, { SET_INPUT_SURFACE, "SET_INPUT_SURFACE" }, 1388da853ecaSopenharmony_ci { SET_OUTPUT_SURFACE, "SET_OUTPUT_SURFACE" }, { START, "START" }, 1389da853ecaSopenharmony_ci { GET_INPUT_FORMAT, "GET_INPUT_FORMAT" }, { GET_OUTPUT_FORMAT, "GET_OUTPUT_FORMAT" }, 1390da853ecaSopenharmony_ci { SET_PARAMETERS, "SET_PARAMETERS" }, { REQUEST_IDR_FRAME, "REQUEST_IDR_FRAME" }, 1391da853ecaSopenharmony_ci { FLUSH, "FLUSH" }, { QUEUE_INPUT_BUFFER, "QUEUE_INPUT_BUFFER" }, 1392da853ecaSopenharmony_ci { NOTIFY_EOS, "NOTIFY_EOS" }, { RELEASE_OUTPUT_BUFFER, "RELEASE_OUTPUT_BUFFER" }, 1393da853ecaSopenharmony_ci { RENDER_OUTPUT_BUFFER, "RENDER_OUTPUT_BUFFER" }, { STOP, "STOP" }, { RELEASE, "RELEASE" }, 1394da853ecaSopenharmony_ci { CODEC_EVENT, "CODEC_EVENT" }, { OMX_EMPTY_BUFFER_DONE, "OMX_EMPTY_BUFFER_DONE" }, 1395da853ecaSopenharmony_ci { OMX_FILL_BUFFER_DONE, "OMX_FILL_BUFFER_DONE" }, { GET_BUFFER_FROM_SURFACE, "GET_BUFFER_FROM_SURFACE" }, 1396da853ecaSopenharmony_ci { CHECK_IF_STUCK, "CHECK_IF_STUCK" }, { FORCE_SHUTDOWN, "FORCE_SHUTDOWN" }, 1397da853ecaSopenharmony_ci }; 1398da853ecaSopenharmony_ci auto it = m.find(what); 1399da853ecaSopenharmony_ci if (it != m.end()) { 1400da853ecaSopenharmony_ci return it->second; 1401da853ecaSopenharmony_ci } 1402da853ecaSopenharmony_ci return "UNKNOWN"; 1403da853ecaSopenharmony_ci} 1404da853ecaSopenharmony_ci} // namespace OHOS::MediaAVCodec