1 /* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef HCODEC_HCODEC_H 17 #define HCODEC_HCODEC_H 18 19 #include <queue> 20 #include <array> 21 #include <functional> 22 #include <unordered_set> 23 #include "securec.h" 24 #include "OMX_Component.h" // third_party/openmax/api/1.1.2 25 #include "codecbase.h" 26 #include "avcodec_errors.h" 27 #include "state_machine.h" 28 #include "codec_hdi.h" 29 #include "type_converter.h" 30 #include "buffer/avbuffer.h" 31 32 namespace OHOS::MediaAVCodec { 33 using TimePoint = std::chrono::time_point<std::chrono::steady_clock>; 34 35 class HCodec : public CodecBase, protected StateMachine { 36 public: 37 static std::shared_ptr<HCodec> Create(const std::string &name); 38 int32_t Init(Media::Meta &callerInfo) override; 39 int32_t SetCallback(const std::shared_ptr<MediaCodecCallback> &callback) override; 40 int32_t Configure(const Format &format) override; 41 int32_t SetCustomBuffer(std::shared_ptr<AVBuffer> buffer) override; 42 sptr<Surface> CreateInputSurface() override; 43 int32_t SetInputSurface(sptr<Surface> surface) override; 44 int32_t SetOutputSurface(sptr<Surface> surface) override; 45 46 int32_t QueueInputBuffer(uint32_t index) override; 47 int32_t NotifyEos() override; 48 int32_t ReleaseOutputBuffer(uint32_t index) override; 49 int32_t RenderOutputBuffer(uint32_t index) override; 50 51 int32_t SignalRequestIDRFrame() override; 52 int32_t SetParameter(const Format& format) override; 53 int32_t GetChannelId(int32_t &channelId) override; 54 int32_t GetInputFormat(Format& format) override; 55 int32_t GetOutputFormat(Format& format) override; 56 std::string GetHidumperInfo() override; 57 int32_t SetLowPowerPlayerMode(bool isLpp) override; 58 59 int32_t Start() override; 60 int32_t Stop() override; 61 int32_t Flush() override; 62 int32_t Reset() override; 63 int32_t Release() override; 64 int32_t NotifyMemoryRecycle() override; 65 int32_t NotifyMemoryWriteBack() override; 66 int32_t NotifySuspend() override; 67 int32_t NotifyResume() override; 68 69 protected: 70 enum MsgWhat : MsgType { 71 INIT, 72 SET_CALLBACK, 73 CONFIGURE, 74 CONFIGURE_BUFFER, 75 CREATE_INPUT_SURFACE, 76 SET_INPUT_SURFACE, 77 SET_OUTPUT_SURFACE, 78 START, 79 GET_INPUT_FORMAT, 80 GET_OUTPUT_FORMAT, 81 SET_PARAMETERS, 82 REQUEST_IDR_FRAME, 83 FLUSH, 84 QUEUE_INPUT_BUFFER, 85 NOTIFY_EOS, 86 RELEASE_OUTPUT_BUFFER, 87 RENDER_OUTPUT_BUFFER, 88 STOP, 89 RELEASE, 90 SUSPEND, 91 RESUME, 92 BUFFER_RECYCLE, 93 BUFFER_WRITEBACK, 94 GET_HIDUMPER_INFO, 95 PRINT_ALL_BUFFER_OWNER, 96 97 INNER_MSG_BEGIN = 1000, 98 CODEC_EVENT, 99 OMX_EMPTY_BUFFER_DONE, 100 OMX_FILL_BUFFER_DONE, 101 GET_BUFFER_FROM_SURFACE, 102 CHECK_IF_REPEAT, 103 SUBMIT_DYNAMIC_IF_EOS, 104 CHECK_IF_STUCK, 105 FORCE_SHUTDOWN, 106 }; 107 108 enum BufferOperationMode { 109 KEEP_BUFFER, 110 RESUBMIT_BUFFER, 111 FREE_BUFFER, 112 }; 113 114 enum BufferOwner { 115 OWNED_BY_US = 0, 116 OWNED_BY_USER = 1, 117 OWNED_BY_OMX = 2, 118 OWNED_BY_SURFACE = 3, 119 OWNER_CNT = 4, 120 }; 121 122 struct PortInfo { 123 uint32_t width = 0; 124 uint32_t height = 0; 125 OMX_VIDEO_CODINGTYPE codingType; 126 std::optional<PixelFmt> pixelFmt; 127 double frameRate; 128 std::optional<uint32_t> inputBufSize; 129 }; 130 131 enum DumpMode : unsigned long { 132 DUMP_NONE = 0, 133 DUMP_ENCODER_INPUT = 0b1000, 134 DUMP_ENCODER_OUTPUT = 0b0100, 135 DUMP_DECODER_INPUT = 0b0010, 136 DUMP_DECODER_OUTPUT = 0b0001, 137 }; 138 139 struct TotalEvent { 140 uint64_t eventCnt = 0; 141 uint64_t eventSum = 0; 142 }; 143 144 struct IntervalAverage { 145 double fps; 146 double mbps; 147 double holdCnt[OWNER_CNT]; 148 double holdMs[OWNER_CNT]; 149 }; 150 151 struct Record { ResetIntervalRecord152 void ResetInterval(std::optional<TimePoint> beginOfInterval) 153 { 154 beginOfInterval_ = beginOfInterval; 155 holdTimeInterval_.fill(TotalEvent{0, 0}); 156 holdCntInterval_.fill(TotalEvent{0, 0}); 157 frameCntInterval_ = 0; 158 frameMbitsInterval_ = 0; 159 discardCntInterval_ = 0; 160 waitFenceCostUsInterval_ = 0; 161 } ResetAllRecord162 void ResetAll() 163 { 164 ResetInterval(std::nullopt); 165 frameCntTotal_ = 0; 166 currOwner_.fill(0); 167 lastOwnerChangeTime_.fill(std::nullopt); 168 lastPts_ = -1; 169 } 170 // 不变值 171 std::array<std::string, OWNER_CNT> ownerTraceTag_; 172 // 从构造开始到某一刻的统计值 173 uint64_t frameCntTotal_ = 0; // 送帧/出帧总数 174 // 当前统计区间的起始时刻点 175 std::optional<TimePoint> beginOfInterval_; 176 // 从起始到某一刻的统计值 177 std::array<TotalEvent, OWNER_CNT> holdTimeInterval_; // 每个轮转方持有单个buffer时长的总值 178 std::array<TotalEvent, OWNER_CNT> holdCntInterval_; // 每个轮转方持有buffer数量乘以持有时长的总值 179 uint64_t frameCntInterval_ = 0; // 送帧/出帧总个数 180 double frameMbitsInterval_ = 0; // 送帧/出帧总M比特数 181 uint64_t discardCntInterval_ = 0; // 丢帧总数 182 uint64_t waitFenceCostUsInterval_ = 0; // 等fence的总耗时 183 // 某一刻的瞬时值 184 std::array<int, OWNER_CNT> currOwner_; // 此刻每个轮转方持有几个buffer 185 std::array<std::optional<TimePoint>, OWNER_CNT> lastOwnerChangeTime_; // 每个轮转方最新一次轮转发生在哪个时刻 186 int64_t lastPts_ = -1; // 最新的一帧的pts 187 } record_[2]; // 2: port count 188 189 struct BufferInfo { BufferInfoBufferInfo190 BufferInfo(bool isIn, BufferOwner beginOwner, Record (&record)[2]) // 2: port count 191 : isInput(isIn), owner(beginOwner), lastOwnerChangeTime(std::chrono::steady_clock::now()) 192 { 193 record[isInput ? OMX_DirInput : OMX_DirOutput].lastOwnerChangeTime_[owner] = lastOwnerChangeTime; 194 } 195 bool isInput; 196 BufferOwner owner; 197 BufferOwner nextStepOwner = OWNER_CNT; 198 TimePoint lastOwnerChangeTime; 199 int64_t lastFlushTime = 0; 200 uint32_t bufferId = 0; 201 std::shared_ptr<CodecHDI::OmxCodecBuffer> omxBuffer; 202 std::shared_ptr<AVBuffer> avBuffer; 203 sptr<SurfaceBuffer> surfaceBuffer; 204 bool attached = false; 205 bool needDealWithCache = false; 206 bool hasSwapedOut = false; 207 208 void CleanUpUnusedInfo(); 209 void BeginCpuAccess(); 210 void EndCpuAccess(); 211 bool IsValidFrame() const; 212 #ifdef BUILD_ENG_VERSION 213 void Dump(const std::string& prefix, uint64_t cnt, DumpMode dumpMode, bool isEncoder) const; 214 215 private: 216 void Dump(const std::string& prefix, uint64_t cnt) const; 217 void DumpSurfaceBuffer(const std::string& prefix, uint64_t cnt) const; 218 void DecideDumpInfo(int& alignedH, uint32_t& totalSize, std::string& suffix, bool& dumpAsVideo) const; 219 void DumpLinearBuffer(const std::string& prefix) const; 220 static constexpr char DUMP_PATH[] = "/data/misc/hcodecdump"; 221 #endif 222 }; 223 224 protected: 225 HCodec(CodecHDI::CodecCompCapability caps, OMX_VIDEO_CODINGTYPE codingType, bool isEncoder); 226 ~HCodec() override; 227 static const char* ToString(MsgWhat what); 228 static const char* ToString(BufferOwner owner); 229 void ReplyErrorCode(MsgId id, int32_t err); 230 void UpdateOwner(); 231 void UpdateOwner(OMX_DIRTYPE port); 232 void ReduceOwner(OMX_DIRTYPE port, BufferOwner owner); 233 void ChangeOwner(BufferInfo& info, BufferOwner newOwner); 234 void OnPrintAllBufferOwner(const MsgInfo& msg); 235 void PrintAllBufferInfo(); 236 std::string OnGetHidumperInfo(); 237 238 void PrintAllBufferInfo(const TimePoint& now, OMX_DIRTYPE port); 239 void UpdateHoldCnt(const TimePoint& now, OMX_DIRTYPE port, BufferOwner owner); 240 void UpdateHoldTime(const TimePoint& now, const BufferInfo& info, BufferOwner newOwner); 241 bool CalculateInterval(const TimePoint& now, OMX_DIRTYPE port, IntervalAverage& ave); 242 void PrintStatistic(const TimePoint& now, OMX_DIRTYPE port); 243 void UpdateInputRecord(const TimePoint& now, const BufferInfo& info); 244 void UpdateOutputRecord(const TimePoint& now, const BufferInfo& info); 245 void FaultEventWrite(const std::string& faultType, const std::string& msg); 246 247 // configure 248 virtual int32_t OnConfigure(const Format &format) = 0; OnConfigureBuffer(std::shared_ptr<AVBuffer> buffer)249 virtual int32_t OnConfigureBuffer(std::shared_ptr<AVBuffer> buffer) { return AVCS_ERR_UNSUPPORT; } 250 bool GetPixelFmtFromUser(const Format &format); 251 static std::optional<double> GetFrameRateFromUser(const Format &format); 252 int32_t SetVideoPortInfo(OMX_DIRTYPE portIndex, const PortInfo& info); 253 virtual int32_t UpdateInPortFormat() = 0; 254 virtual int32_t UpdateOutPortFormat() = 0; UpdateColorAspects()255 virtual void UpdateColorAspects() {} 256 void PrintPortDefinition(const OMX_PARAM_PORTDEFINITIONTYPE& def); 257 int32_t SetFrameRateAdaptiveMode(const Format &format); 258 int32_t SetProcessName(); 259 int32_t SetLowLatency(const Format &format); 260 261 virtual void OnSetOutputSurface(const MsgInfo &msg, BufferOperationMode mode); OnSetParameters(const Format & format)262 virtual int32_t OnSetParameters(const Format &format) { return AVCS_ERR_OK; } OnCreateInputSurface()263 virtual sptr<Surface> OnCreateInputSurface() { return nullptr; } OnSetInputSurface(sptr<Surface> & inputSurface)264 virtual int32_t OnSetInputSurface(sptr<Surface> &inputSurface) { return AVCS_ERR_UNSUPPORT; } RequestIDRFrame()265 virtual int32_t RequestIDRFrame() { return AVCS_ERR_UNSUPPORT; } 266 267 // start 268 virtual bool ReadyToStart() = 0; 269 virtual int32_t AllocateBuffersOnPort(OMX_DIRTYPE portIndex) = 0; 270 void SetCallerToBuffer(int fd, uint32_t w, uint32_t h); 271 virtual void UpdateFmtFromSurfaceBuffer() = 0; 272 int32_t GetPortDefinition(OMX_DIRTYPE portIndex, OMX_PARAM_PORTDEFINITIONTYPE& def); 273 int32_t AllocateAvSurfaceBuffers(OMX_DIRTYPE portIndex); 274 int32_t AllocateAvLinearBuffers(OMX_DIRTYPE portIndex); 275 int32_t AllocateAvHardwareBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def); 276 int32_t AllocateAvSharedBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def); 277 std::shared_ptr<CodecHDI::OmxCodecBuffer> SurfaceBufferToOmxBuffer( 278 const sptr<SurfaceBuffer>& surfaceBuffer); 279 std::shared_ptr<CodecHDI::OmxCodecBuffer> DynamicSurfaceBufferToOmxBuffer(); 280 281 virtual int32_t SubmitAllBuffersOwnedByUs() = 0; SubmitOutBufToOmx()282 virtual int32_t SubmitOutBufToOmx() { return AVCS_ERR_UNSUPPORT; } 283 BufferInfo* FindBufferInfoByID(OMX_DIRTYPE portIndex, uint32_t bufferId); 284 std::optional<size_t> FindBufferIndexByID(OMX_DIRTYPE portIndex, uint32_t bufferId); 285 virtual void OnGetBufferFromSurface(const ParamSP& param) = 0; 286 uint32_t UserFlagToOmxFlag(AVCodecBufferFlag userFlag); 287 AVCodecBufferFlag OmxFlagToUserFlag(uint32_t omxFlag); 288 bool WaitFence(const sptr<SyncFence>& fence); 289 void WrapSurfaceBufferToSlot(BufferInfo &info, 290 const sptr<SurfaceBuffer>& surfaceBuffer, int64_t pts, uint32_t flag); 291 292 // input buffer circulation 293 virtual void NotifyUserToFillThisInBuffer(BufferInfo &info); 294 virtual void OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode); 295 int32_t OnQueueInputBuffer(BufferOperationMode mode, BufferInfo* info); 296 virtual void OnSignalEndOfInputStream(const MsgInfo &msg); 297 int32_t InBufUsToOmx(BufferInfo& info); 298 virtual void OnOMXEmptyBufferDone(uint32_t bufferId, BufferOperationMode mode) = 0; RepeatIfNecessary(const ParamSP & param)299 virtual void RepeatIfNecessary(const ParamSP& param) {} 300 bool CheckBufPixFmt(const sptr<SurfaceBuffer>& buffer); 301 302 // output buffer circulation DynamicModeSubmitBuffer()303 virtual void DynamicModeSubmitBuffer() {} DynamicModeSubmitIfEos()304 virtual void DynamicModeSubmitIfEos() {} 305 int32_t NotifyOmxToFillThisOutBuffer(BufferInfo &info); 306 void OnOMXFillBufferDone(const CodecHDI::OmxCodecBuffer& omxBuffer, BufferOperationMode mode); 307 void OnOMXFillBufferDone(BufferOperationMode mode, BufferInfo& info, size_t bufferIdx); 308 void OutBufUsToUser(BufferInfo &info); 309 void OnReleaseOutputBuffer(const MsgInfo &msg, BufferOperationMode mode); 310 void OnReleaseOutputBuffer(uint32_t bufferId, BufferOperationMode mode); OnReleaseOutputBuffer(const BufferInfo & info)311 virtual void OnReleaseOutputBuffer(const BufferInfo &info) {} 312 virtual void OnRenderOutputBuffer(const MsgInfo &msg, BufferOperationMode mode); BeforeCbOutToUser(BufferInfo & info)313 virtual void BeforeCbOutToUser(BufferInfo &info) {} ProcSurfaceBufferToUser(const sptr<SurfaceBuffer> & buffer)314 virtual void ProcSurfaceBufferToUser(const sptr<SurfaceBuffer>& buffer) {} ProcAVBufferToUser(std::shared_ptr<AVBuffer> avBuffer,std::shared_ptr<CodecHDI::OmxCodecBuffer> omxBuffer)315 virtual void ProcAVBufferToUser(std::shared_ptr<AVBuffer> avBuffer, 316 std::shared_ptr<CodecHDI::OmxCodecBuffer> omxBuffer) {} 317 void RecordBufferStatus(OMX_DIRTYPE portIndex, uint32_t bufferId, BufferOwner nextOwner); SubmitBuffersToNextOwner()318 virtual void SubmitBuffersToNextOwner() {} 319 320 // stop/release 321 void ReclaimBuffer(OMX_DIRTYPE portIndex, BufferOwner owner, bool erase = false); 322 bool IsAllBufferOwnedByUsOrSurface(OMX_DIRTYPE portIndex); 323 bool IsAllBufferOwnedByUsOrSurface(); 324 void EraseOutBuffersOwnedByUsOrSurface(); 325 void ClearBufferPool(OMX_DIRTYPE portIndex); OnClearBufferPool(OMX_DIRTYPE portIndex)326 virtual void OnClearBufferPool(OMX_DIRTYPE portIndex) {} 327 virtual void EraseBufferFromPool(OMX_DIRTYPE portIndex, size_t i) = 0; 328 void FreeOmxBuffer(OMX_DIRTYPE portIndex, const BufferInfo& info); OnEnterUninitializedState()329 virtual void OnEnterUninitializedState() {} 330 331 // freeze FreezeBuffers()332 virtual int32_t FreezeBuffers() { return AVCS_ERR_UNSUPPORT; } ActiveBuffers()333 virtual int32_t ActiveBuffers() { return AVCS_ERR_UNSUPPORT; } DecreaseFreq()334 virtual int32_t DecreaseFreq() { return AVCS_ERR_UNSUPPORT; } RecoverFreq()335 virtual int32_t RecoverFreq() { return AVCS_ERR_UNSUPPORT; } 336 337 // template 338 template <typename T> InitOMXParam(T & param)339 static inline void InitOMXParam(T& param) 340 { 341 (void)memset_s(¶m, sizeof(T), 0x0, sizeof(T)); 342 param.nSize = sizeof(T); 343 param.nVersion.s.nVersionMajor = 1; 344 } 345 346 template <typename T> InitOMXParamExt(T & param)347 static inline void InitOMXParamExt(T& param) 348 { 349 (void)memset_s(¶m, sizeof(T), 0x0, sizeof(T)); 350 param.size = sizeof(T); 351 param.version.s.nVersionMajor = 1; 352 } 353 354 template <typename T> 355 bool GetParameter(uint32_t index, T& param, bool isCfg = false) 356 { 357 int8_t* p = reinterpret_cast<int8_t*>(¶m); 358 std::vector<int8_t> inVec(p, p + sizeof(T)); 359 std::vector<int8_t> outVec; 360 int32_t ret = isCfg ? compNode_->GetConfig(index, inVec, outVec) : 361 compNode_->GetParameter(index, inVec, outVec); 362 if (ret != HDF_SUCCESS) { 363 return false; 364 } 365 if (outVec.size() != sizeof(T)) { 366 return false; 367 } 368 ret = memcpy_s(¶m, sizeof(T), outVec.data(), outVec.size()); 369 if (ret != EOK) { 370 return false; 371 } 372 return true; 373 } 374 375 template <typename T> 376 bool SetParameter(uint32_t index, const T& param, bool isCfg = false) 377 { 378 const int8_t* p = reinterpret_cast<const int8_t*>(¶m); 379 std::vector<int8_t> inVec(p, p + sizeof(T)); 380 int32_t ret = isCfg ? compNode_->SetConfig(index, inVec) : 381 compNode_->SetParameter(index, inVec); 382 if (ret != HDF_SUCCESS) { 383 return false; 384 } 385 return true; 386 } 387 AlignTo(uint32_t side,uint32_t align)388 static inline uint32_t AlignTo(uint32_t side, uint32_t align) 389 { 390 if (align == 0) { 391 return side; 392 } 393 return (side + align - 1) / align * align; 394 } 395 396 protected: 397 CodecHDI::CodecCompCapability caps_; 398 OMX_VIDEO_CODINGTYPE codingType_; 399 bool isEncoder_; 400 bool isSecure_ = false; 401 std::string mime_; 402 uint32_t componentId_ = 0; 403 std::string compUniqueStr_; 404 int32_t instanceId_ = -1; 405 struct CallerInfo { 406 int32_t pid = -1; 407 std::string processName; 408 }; 409 struct Caller { 410 CallerInfo playerCaller; 411 CallerInfo avcodecCaller; 412 CallerInfo app; 413 bool calledByAvcodec = true; 414 } caller_; 415 static std::shared_mutex g_mtx; 416 static std::unordered_map<std::string, HCodec::Caller> g_callers; 417 418 bool debugMode_ = false; 419 bool disableDmaSwap_ = false; 420 DumpMode dumpMode_ = DUMP_NONE; 421 sptr<CodecHDI::ICodecCallback> compCb_ = nullptr; 422 sptr<CodecHDI::ICodecComponent> compNode_ = nullptr; 423 sptr<CodecHDI::ICodecComponentManager> compMgr_ = nullptr; 424 425 std::shared_ptr<MediaCodecCallback> callback_; 426 PixelFmt configuredFmt_{}; 427 BufferRequestConfig requestCfg_{}; 428 std::shared_ptr<Format> configFormat_; 429 std::shared_ptr<Format> inputFormat_; 430 std::shared_ptr<Format> outputFormat_; 431 432 std::vector<BufferInfo> inputBufferPool_; 433 std::vector<BufferInfo> outputBufferPool_; 434 std::queue<uint32_t> inputBufIdQueueToOmx_; 435 bool isBufferCirculating_ = false; 436 bool inputPortEos_ = false; 437 bool outputPortEos_ = false; 438 bool gotFirstInput_ = false; 439 bool gotFirstOutput_ = false; 440 bool outPortHasChanged_ = false; 441 int pid_ = -1; 442 bool isLpp_ = false; 443 double codecRate_ = 0.0; 444 445 // VRR 446 bool isVrrInitialized_ = false; 447 #ifdef USE_VIDEO_PROCESSING_ENGINE VrrPrediction(BufferInfo & info)448 virtual int32_t VrrPrediction(BufferInfo &info) { return AVCS_ERR_UNSUPPORT; } 449 #endif 450 451 std::unordered_map<int64_t, TimePoint> inTimeMap_; 452 uint64_t onePtsInToOutTotalCostUs_ = 0; 453 static constexpr uint64_t PRINT_PER_FRAME = 400; 454 // used when buffer circulation stoped 455 static constexpr char KEY_LAST_OWNER_CHANGE_TIME[] = "lastOwnerChangeTime"; 456 TimePoint lastOwnerChangeTime_; 457 bool circulateHasStopped_ = false; 458 459 static constexpr char BUFFER_ID[] = "buffer-id"; 460 static constexpr uint32_t WAIT_FENCE_MS = 1000; 461 static constexpr uint32_t STRIDE_ALIGNMENT = 32; 462 static constexpr double FRAME_RATE_COEFFICIENT = 65536.0; 463 static constexpr double BYTE_TO_MBIT = 8.0 / 1024.0 / 1024.0; 464 465 private: 466 struct BaseState : State { 467 protected: 468 BaseState(HCodec *codec, const std::string &stateName, 469 BufferOperationMode inputMode = KEEP_BUFFER, BufferOperationMode outputMode = KEEP_BUFFER) StateBaseState470 : State(stateName), codec_(codec), inputMode_(inputMode), outputMode_(outputMode) {} 471 void OnMsgReceived(const MsgInfo &info) override; 472 void ReplyErrorCode(MsgId id, int32_t err); 473 void OnCodecEvent(const MsgInfo &info); 474 virtual void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2); 475 void OnGetFormat(const MsgInfo &info); 476 virtual void OnShutDown(const MsgInfo &info) = 0; 477 virtual void OnCheckIfStuck(const MsgInfo &info); 478 void OnForceShutDown(const MsgInfo &info); OnStateExitedBaseState479 void OnStateExited() override { codec_->stateGeneration_++; } 480 void OnSetParameters(const MsgInfo &info); 481 void OnSuspend(const MsgInfo &info); 482 void OnResume(const MsgInfo &info); 483 484 protected: 485 HCodec *codec_; 486 BufferOperationMode inputMode_; 487 BufferOperationMode outputMode_; 488 }; 489 490 struct UninitializedState : BaseState { UninitializedStateUninitializedState491 explicit UninitializedState(HCodec *codec) : BaseState(codec, "Uninit") {} 492 private: 493 void OnStateEntered() override; 494 void OnMsgReceived(const MsgInfo &info) override; 495 void OnShutDown(const MsgInfo &info) override; 496 }; 497 498 struct InitializedState : BaseState { InitializedStateInitializedState499 explicit InitializedState(HCodec *codec) : BaseState(codec, "Init") {} 500 private: 501 void OnStateEntered() override; 502 void ProcessShutDownFromRunning(); 503 void OnMsgReceived(const MsgInfo &info) override; 504 void OnSetCallBack(const MsgInfo &info); 505 void OnConfigure(const MsgInfo &info); 506 void OnStart(const MsgInfo &info); 507 void OnShutDown(const MsgInfo &info) override; 508 }; 509 510 struct StartingState : BaseState { StartingStateStartingState511 explicit StartingState(HCodec *codec) : BaseState(codec, "Start") {} 512 private: 513 void OnStateEntered() override; 514 void OnStateExited() override; 515 void OnMsgReceived(const MsgInfo &info) override; 516 int32_t AllocateBuffers(); 517 void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override; 518 void OnShutDown(const MsgInfo &info) override; 519 void ReplyStartMsg(int32_t errCode); 520 bool hasError_ = false; 521 }; 522 523 struct RunningState : BaseState { RunningStateRunningState524 explicit RunningState(HCodec *codec) : BaseState(codec, "Run", RESUBMIT_BUFFER, RESUBMIT_BUFFER) {} 525 private: 526 void OnStateEntered() override; 527 void OnMsgReceived(const MsgInfo &info) override; 528 void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override; 529 void OnShutDown(const MsgInfo &info) override; 530 void OnFlush(const MsgInfo &info); 531 void OnBufferRecycle(const MsgInfo &info); 532 }; 533 534 struct OutputPortChangedState : BaseState { OutputPortChangedStateOutputPortChangedState535 explicit OutputPortChangedState(HCodec *codec) 536 : BaseState(codec, "OutChange", RESUBMIT_BUFFER, FREE_BUFFER) {} 537 private: 538 void OnStateEntered() override; 539 void OnMsgReceived(const MsgInfo &info) override; 540 void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override; 541 void OnShutDown(const MsgInfo &info) override; 542 void HandleOutputPortDisabled(); 543 void HandleOutputPortEnabled(); 544 void OnFlush(const MsgInfo &info); 545 void OnCheckIfStuck(const MsgInfo &info) override; 546 }; 547 548 struct FlushingState : BaseState { FlushingStateFlushingState549 explicit FlushingState(HCodec *codec) : BaseState(codec, "Flush") {} 550 private: 551 void OnStateEntered() override; 552 void OnMsgReceived(const MsgInfo &info) override; 553 void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override; 554 void OnShutDown(const MsgInfo &info) override; 555 void ChangeStateIfWeOwnAllBuffers(); 556 bool IsFlushCompleteOnAllPorts(); 557 int32_t UpdateFlushStatusOnPorts(uint32_t data1, uint32_t data2); 558 bool flushCompleteFlag_[2] {false, false}; 559 }; 560 561 struct StoppingState : BaseState { StoppingStateStoppingState562 explicit StoppingState(HCodec *codec) : BaseState(codec, "Stop"), 563 omxNodeInIdleState_(false), 564 omxNodeIsChangingToLoadedState_(false) {} 565 private: 566 void OnStateEntered() override; 567 void OnMsgReceived(const MsgInfo &info) override; 568 void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override; 569 void OnShutDown(const MsgInfo &info) override; 570 void ChangeStateIfWeOwnAllBuffers(); 571 void ChangeOmxNodeToLoadedState(bool forceToFreeBuffer); 572 bool omxNodeInIdleState_; 573 bool omxNodeIsChangingToLoadedState_; 574 }; 575 576 struct FrozenState : BaseState { FrozenStateFrozenState577 explicit FrozenState(HCodec *codec) : BaseState(codec, "Frozen") {} 578 private: 579 void OnMsgReceived(const MsgInfo &info) override; 580 void OnShutDown(const MsgInfo &info) override; 581 void OnBufferWriteback(const MsgInfo &info); 582 }; 583 584 class HdiCallback : public CodecHDI::ICodecCallback { 585 public: HdiCallback(std::weak_ptr<MsgToken> codec)586 explicit HdiCallback(std::weak_ptr<MsgToken> codec) : codec_(codec) { } 587 virtual ~HdiCallback() = default; 588 int32_t EventHandler(CodecHDI::CodecEventType event, 589 const CodecHDI::EventInfo& info); 590 int32_t EmptyBufferDone(int64_t appData, const CodecHDI::OmxCodecBuffer& buffer); 591 int32_t FillBufferDone(int64_t appData, const CodecHDI::OmxCodecBuffer& buffer); 592 private: 593 std::weak_ptr<MsgToken> codec_; 594 }; 595 596 private: 597 int32_t DoSyncCall(MsgWhat msgType, std::function<void(ParamSP)> oper, uint32_t waitMs = FIVE_SECONDS_IN_MS); 598 int32_t DoSyncCallAndGetReply(MsgWhat msgType, std::function<void(ParamSP)> oper, ParamSP &reply, 599 uint32_t waitMs = FIVE_SECONDS_IN_MS); 600 void PrintCaller(); 601 void PrintAllCaller(); 602 void RemoveCaller(); 603 int32_t OnAllocateComponent(); 604 void ReleaseComponent(); 605 void CleanUpOmxNode(); 606 void ChangeOmxToTargetState(CodecHDI::CodecStateType &state, 607 CodecHDI::CodecStateType targetState); 608 bool RollOmxBackToLoaded(); 609 610 int32_t ForceShutdown(int32_t generation, bool isNeedNotifyCaller); 611 void SignalError(AVCodecErrorType errorType, int32_t errorCode); 612 void DeferMessage(const MsgInfo &info); 613 void ProcessDeferredMessages(); 614 void ReplyToSyncMsgLater(const MsgInfo& msg); 615 bool GetFirstSyncMsgToReply(MsgInfo& msg); 616 617 private: 618 static constexpr size_t MAX_HCODEC_BUFFER_SIZE = 8192 * 4096 * 4; // 8K RGBA 619 static constexpr uint32_t THREE_SECONDS_IN_US = 3'000'000; 620 static constexpr uint32_t ONE_SECONDS_IN_US = 1'000'000; 621 static constexpr uint32_t FIVE_SECONDS_IN_MS = 5'000; 622 static constexpr double HIGH_FPS = 120.0; 623 static constexpr char HISYSEVENT_DOMAIN_HCODEC[] = "AV_CODEC"; 624 625 std::shared_ptr<UninitializedState> uninitializedState_; 626 std::shared_ptr<InitializedState> initializedState_; 627 std::shared_ptr<StartingState> startingState_; 628 std::shared_ptr<RunningState> runningState_; 629 std::shared_ptr<OutputPortChangedState> outputPortChangedState_; 630 std::shared_ptr<FlushingState> flushingState_; 631 std::shared_ptr<StoppingState> stoppingState_; 632 std::shared_ptr<FrozenState> frozenState_; 633 634 int32_t stateGeneration_ = 0; 635 bool isShutDownFromRunning_ = false; 636 bool notifyCallerAfterShutdownComplete_ = false; 637 bool keepComponentAllocated_ = false; 638 bool hasFatalError_ = false; 639 std::list<MsgInfo> deferredQueue_; 640 std::map<MsgType, std::queue<std::pair<MsgId, ParamSP>>> syncMsgToReply_; 641 }; // class HCodec 642 } // namespace OHOS::MediaAVCodec 643 #endif // HCODEC_HCODEC_H 644