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 #include "meta/meta_key.h" // foundation/multimedia/histreamer/interface/inner_api/
32 
33 namespace OHOS::MediaAVCodec {
34 class HCodec : public CodecBase, protected StateMachine, public std::enable_shared_from_this<HCodec> {
35 public:
36     static std::shared_ptr<HCodec> Create(const std::string &name);
37     int32_t Init(Media::Meta &callerInfo) override;
38     int32_t SetCallback(const std::shared_ptr<MediaCodecCallback> &callback) override;
39     int32_t Configure(const Format &format) override;
40     int32_t SetCustomBuffer(std::shared_ptr<AVBuffer> buffer) override;
41     sptr<Surface> CreateInputSurface() override;
42     int32_t SetInputSurface(sptr<Surface> surface) override;
43     int32_t SetOutputSurface(sptr<Surface> surface) override;
44 
45     int32_t QueueInputBuffer(uint32_t index) override;
46     int32_t NotifyEos() override;
47     int32_t ReleaseOutputBuffer(uint32_t index) override;
48     int32_t RenderOutputBuffer(uint32_t index) override;
49 
50     int32_t SignalRequestIDRFrame() override;
51     int32_t SetParameter(const Format& format) override;
52     int32_t GetInputFormat(Format& format) override;
53     int32_t GetOutputFormat(Format& format) override;
54     std::string GetHidumperInfo() override;
55 
56     int32_t Start() override;
57     int32_t Stop() override;
58     int32_t Flush() override;
59     int32_t Reset() override;
60     int32_t Release() override;
OnBufferReleasedByConsumer(uint64_t surfaceId)61     virtual GSError OnBufferReleasedByConsumer(uint64_t surfaceId) { return GSERROR_OK; }
62 
63 protected:
64     enum MsgWhat : MsgType {
65         INIT,
66         SET_CALLBACK,
67         CONFIGURE,
68         CONFIGURE_BUFFER,
69         CREATE_INPUT_SURFACE,
70         SET_INPUT_SURFACE,
71         SET_OUTPUT_SURFACE,
72         START,
73         GET_INPUT_FORMAT,
74         GET_OUTPUT_FORMAT,
75         SET_PARAMETERS,
76         REQUEST_IDR_FRAME,
77         FLUSH,
78         QUEUE_INPUT_BUFFER,
79         NOTIFY_EOS,
80         RELEASE_OUTPUT_BUFFER,
81         RENDER_OUTPUT_BUFFER,
82         STOP,
83         RELEASE,
84         GET_HIDUMPER_INFO,
85         PRINT_ALL_BUFFER_OWNER,
86 
87         INNER_MSG_BEGIN = 1000,
88         CODEC_EVENT,
89         OMX_EMPTY_BUFFER_DONE,
90         OMX_FILL_BUFFER_DONE,
91         GET_BUFFER_FROM_SURFACE,
92         CHECK_IF_REPEAT,
93         CHECK_IF_STUCK,
94         FORCE_SHUTDOWN,
95     };
96 
97     enum BufferOperationMode {
98         KEEP_BUFFER,
99         RESUBMIT_BUFFER,
100         FREE_BUFFER,
101     };
102 
103     enum BufferOwner {
104         OWNED_BY_US = 0,
105         OWNED_BY_USER = 1,
106         OWNED_BY_OMX = 2,
107         OWNED_BY_SURFACE = 3,
108         OWNER_CNT = 4,
109     };
110 
111     struct PortInfo {
112         uint32_t width = 0;
113         uint32_t height = 0;
114         OMX_VIDEO_CODINGTYPE codingType;
115         std::optional<PixelFmt> pixelFmt;
116         double frameRate;
117         std::optional<uint32_t> inputBufSize;
118     };
119 
120     enum DumpMode : unsigned long {
121         DUMP_NONE = 0,
122         DUMP_ENCODER_INPUT = 0b1000,
123         DUMP_ENCODER_OUTPUT = 0b0100,
124         DUMP_DECODER_INPUT = 0b0010,
125         DUMP_DECODER_OUTPUT = 0b0001,
126     };
127 
128     struct BufferInfo {
BufferInfoBufferInfo129         BufferInfo() : lastOwnerChangeTime(std::chrono::steady_clock::now()) {}
130         bool isInput = true;
131         BufferOwner owner = OWNED_BY_US;
132         std::chrono::time_point<std::chrono::steady_clock> lastOwnerChangeTime;
133         int64_t lastFlushTime = 0;
134         uint32_t bufferId = 0;
135         std::shared_ptr<CodecHDI::OmxCodecBuffer> omxBuffer;
136         std::shared_ptr<AVBuffer> avBuffer;
137         sptr<SurfaceBuffer> surfaceBuffer;
138         bool needDealWithCache = false;
139 
140         void CleanUpUnusedInfo();
141         void BeginCpuAccess();
142         void EndCpuAccess();
143         bool IsValidFrame() const;
144 #ifdef BUILD_ENG_VERSION
145         void Dump(const std::string& prefix, uint64_t cnt, DumpMode dumpMode, bool isEncoder) const;
146 
147     private:
148         void Dump(const std::string& prefix, uint64_t cnt) const;
149         void DumpSurfaceBuffer(const std::string& prefix, uint64_t cnt) const;
150         void DecideDumpInfo(int& alignedH, uint32_t& totalSize, std::string& suffix, bool& dumpAsVideo) const;
151         void DumpLinearBuffer(const std::string& prefix) const;
152         static constexpr char DUMP_PATH[] = "/data/misc/hcodecdump";
153 #endif
154     };
155 
156 protected:
157     HCodec(CodecHDI::CodecCompCapability caps, OMX_VIDEO_CODINGTYPE codingType, bool isEncoder);
158     ~HCodec() override;
159     static const char* ToString(MsgWhat what);
160     static const char* ToString(BufferOwner owner);
161     void ReplyErrorCode(MsgId id, int32_t err);
162     void OnPrintAllBufferOwner(const MsgInfo& msg);
163     void PrintAllBufferInfo();
164     void PrintAllBufferInfo(bool isInput, std::chrono::time_point<std::chrono::steady_clock> now);
165     void PrintStatistic(bool isInput, std::chrono::time_point<std::chrono::steady_clock> now);
166     std::string OnGetHidumperInfo();
167     void UpdateOwner();
168     void UpdateOwner(bool isInput);
169     void ReduceOwner(bool isInput, BufferOwner owner);
170     void ChangeOwner(BufferInfo& info, BufferOwner newOwner);
171     void ChangeOwnerNormal(BufferInfo& info, BufferOwner newOwner);
172     void ChangeOwnerDebug(BufferInfo& info, BufferOwner newOwner);
173     void UpdateInputRecord(const BufferInfo& info, std::chrono::time_point<std::chrono::steady_clock> now);
174     void UpdateOutputRecord(const BufferInfo& info, std::chrono::time_point<std::chrono::steady_clock> now);
175 
176     // configure
177     virtual int32_t OnConfigure(const Format &format) = 0;
OnConfigureBuffer(std::shared_ptr<AVBuffer> buffer)178     virtual int32_t OnConfigureBuffer(std::shared_ptr<AVBuffer> buffer) { return AVCS_ERR_UNSUPPORT; }
179     bool GetPixelFmtFromUser(const Format &format);
180     static std::optional<double> GetFrameRateFromUser(const Format &format);
181     int32_t SetVideoPortInfo(OMX_DIRTYPE portIndex, const PortInfo& info);
182     virtual int32_t UpdateInPortFormat() = 0;
183     virtual int32_t UpdateOutPortFormat() = 0;
UpdateColorAspects()184     virtual void UpdateColorAspects() {}
185     void PrintPortDefinition(const OMX_PARAM_PORTDEFINITIONTYPE& def);
186     int32_t SetFrameRateAdaptiveMode(const Format &format);
187     int32_t SetProcessName();
188     int32_t SetLowLatency(const Format &format);
189 
OnSetOutputSurface(const sptr<Surface> & surface,bool cfg)190     virtual int32_t OnSetOutputSurface(const sptr<Surface> &surface, bool cfg) { return AVCS_ERR_UNSUPPORT; }
OnSetParameters(const Format & format)191     virtual int32_t OnSetParameters(const Format &format) { return AVCS_ERR_OK; }
OnCreateInputSurface()192     virtual sptr<Surface> OnCreateInputSurface() { return nullptr; }
OnSetInputSurface(sptr<Surface> & inputSurface)193     virtual int32_t OnSetInputSurface(sptr<Surface> &inputSurface) { return AVCS_ERR_UNSUPPORT; }
RequestIDRFrame()194     virtual int32_t RequestIDRFrame() { return AVCS_ERR_UNSUPPORT; }
195 
196     // start
197     virtual bool ReadyToStart() = 0;
198     virtual int32_t AllocateBuffersOnPort(OMX_DIRTYPE portIndex) = 0;
SetCallerToBuffer(int fd)199     virtual void SetCallerToBuffer(int fd) {}
200     virtual void UpdateFormatFromSurfaceBuffer() = 0;
201     int32_t GetPortDefinition(OMX_DIRTYPE portIndex, OMX_PARAM_PORTDEFINITIONTYPE& def);
202     int32_t AllocateAvSurfaceBuffers(OMX_DIRTYPE portIndex);
203     int32_t AllocateAvLinearBuffers(OMX_DIRTYPE portIndex);
204     int32_t AllocateAvHardwareBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def);
205     int32_t AllocateAvSharedBuffers(OMX_DIRTYPE portIndex, const OMX_PARAM_PORTDEFINITIONTYPE& def);
206     std::shared_ptr<CodecHDI::OmxCodecBuffer> SurfaceBufferToOmxBuffer(
207         const sptr<SurfaceBuffer>& surfaceBuffer);
208     std::shared_ptr<CodecHDI::OmxCodecBuffer> DynamicSurfaceBufferToOmxBuffer();
209 
210     virtual int32_t SubmitAllBuffersOwnedByUs() = 0;
SubmitOutputBuffersToOmxNode()211     virtual int32_t SubmitOutputBuffersToOmxNode() { return AVCS_ERR_UNSUPPORT; }
212     BufferInfo* FindBufferInfoByID(OMX_DIRTYPE portIndex, uint32_t bufferId);
213     std::optional<size_t> FindBufferIndexByID(OMX_DIRTYPE portIndex, uint32_t bufferId);
214     virtual void OnGetBufferFromSurface(const ParamSP& param) = 0;
215     uint32_t UserFlagToOmxFlag(AVCodecBufferFlag userFlag);
216     AVCodecBufferFlag OmxFlagToUserFlag(uint32_t omxFlag);
217     bool WaitFence(const sptr<SyncFence>& fence);
218     void WrapSurfaceBufferToSlot(BufferInfo &info,
219         const sptr<SurfaceBuffer>& surfaceBuffer, int64_t pts, uint32_t flag);
220 
221     // input buffer circulation
222     virtual void NotifyUserToFillThisInBuffer(BufferInfo &info);
223     virtual void OnQueueInputBuffer(const MsgInfo &msg, BufferOperationMode mode);
224     int32_t OnQueueInputBuffer(BufferOperationMode mode, BufferInfo* info);
225     virtual void OnSignalEndOfInputStream(const MsgInfo &msg);
226     int32_t NotifyOmxToEmptyThisInBuffer(BufferInfo& info);
227     virtual void OnOMXEmptyBufferDone(uint32_t bufferId, BufferOperationMode mode) = 0;
RepeatIfNecessary(const ParamSP & param)228     virtual void RepeatIfNecessary(const ParamSP& param) {}
229     bool CheckBufPixFmt(const sptr<SurfaceBuffer>& buffer);
230 
231     // output buffer circulation
SubmitDynamicBufferIfPossible()232     virtual void SubmitDynamicBufferIfPossible() {}
233     int32_t NotifyOmxToFillThisOutBuffer(BufferInfo &info);
234     void OnOMXFillBufferDone(const CodecHDI::OmxCodecBuffer& omxBuffer, BufferOperationMode mode);
235     void OnOMXFillBufferDone(BufferOperationMode mode, BufferInfo& info, size_t bufferIdx);
236     void NotifyUserOutBufferAvaliable(BufferInfo &info);
237     void OnReleaseOutputBuffer(const MsgInfo &msg, BufferOperationMode mode);
OnReleaseOutputBuffer(const BufferInfo & info)238     virtual void OnReleaseOutputBuffer(const BufferInfo &info) {}
239     virtual void OnRenderOutputBuffer(const MsgInfo &msg, BufferOperationMode mode);
ExtractPerFrameParamFromOmxBuffer(const std::shared_ptr<CodecHDI::OmxCodecBuffer> & omxBuffer,std::shared_ptr<Media::Meta> & meta)240     virtual void ExtractPerFrameParamFromOmxBuffer(
241         const std::shared_ptr<CodecHDI::OmxCodecBuffer> &omxBuffer,
242         std::shared_ptr<Media::Meta> &meta) {}
243 
244     // stop/release
245     void ReclaimBuffer(OMX_DIRTYPE portIndex, BufferOwner owner, bool erase = false);
246     bool IsAllBufferOwnedByUsOrSurface(OMX_DIRTYPE portIndex);
247     bool IsAllBufferOwnedByUsOrSurface();
248     void EraseOutBuffersOwnedByUsOrSurface();
249     void ClearBufferPool(OMX_DIRTYPE portIndex);
OnClearBufferPool(OMX_DIRTYPE portIndex)250     virtual void OnClearBufferPool(OMX_DIRTYPE portIndex) {}
251     virtual void EraseBufferFromPool(OMX_DIRTYPE portIndex, size_t i) = 0;
252     void FreeOmxBuffer(OMX_DIRTYPE portIndex, const BufferInfo& info);
OnEnterUninitializedState()253     virtual void OnEnterUninitializedState() {}
254 
255     // template
256     template <typename T>
InitOMXParam(T & param)257     static inline void InitOMXParam(T& param)
258     {
259         (void)memset_s(&param, sizeof(T), 0x0, sizeof(T));
260         param.nSize = sizeof(T);
261         param.nVersion.s.nVersionMajor = 1;
262     }
263 
264     template <typename T>
InitOMXParamExt(T & param)265     static inline void InitOMXParamExt(T& param)
266     {
267         (void)memset_s(&param, sizeof(T), 0x0, sizeof(T));
268         param.size = sizeof(T);
269         param.version.s.nVersionMajor = 1;
270     }
271 
272     template <typename T>
273     bool GetParameter(uint32_t index, T& param, bool isCfg = false)
274     {
275         int8_t* p = reinterpret_cast<int8_t*>(&param);
276         std::vector<int8_t> inVec(p, p + sizeof(T));
277         std::vector<int8_t> outVec;
278         int32_t ret = isCfg ? compNode_->GetConfig(index, inVec, outVec) :
279                               compNode_->GetParameter(index, inVec, outVec);
280         if (ret != HDF_SUCCESS) {
281             return false;
282         }
283         if (outVec.size() != sizeof(T)) {
284             return false;
285         }
286         ret = memcpy_s(&param, sizeof(T), outVec.data(), outVec.size());
287         if (ret != EOK) {
288             return false;
289         }
290         return true;
291     }
292 
293     template <typename T>
294     bool SetParameter(uint32_t index, const T& param, bool isCfg = false)
295     {
296         const int8_t* p = reinterpret_cast<const int8_t*>(&param);
297         std::vector<int8_t> inVec(p, p + sizeof(T));
298         int32_t ret = isCfg ? compNode_->SetConfig(index, inVec) :
299                               compNode_->SetParameter(index, inVec);
300         if (ret != HDF_SUCCESS) {
301             return false;
302         }
303         return true;
304     }
305 
AlignTo(uint32_t side,uint32_t align)306     static inline uint32_t AlignTo(uint32_t side, uint32_t align)
307     {
308         if (align == 0) {
309             return side;
310         }
311         return (side + align - 1) / align * align;
312     }
313 
314 protected:
315     CodecHDI::CodecCompCapability caps_;
316     OMX_VIDEO_CODINGTYPE codingType_;
317     bool isEncoder_;
318     bool isSecure_ = false;
319     std::string shortName_;
320     uint32_t componentId_ = 0;
321     std::string compUniqueStr_;
322     struct CallerInfo {
323         int32_t pid = -1;
324         std::string processName;
325     } playerCaller_, avcodecCaller_;
326     bool calledByAvcodec_ = true;
327     bool debugMode_ = false;
328     DumpMode dumpMode_ = DUMP_NONE;
329     sptr<CodecHDI::ICodecCallback> compCb_ = nullptr;
330     sptr<CodecHDI::ICodecComponent> compNode_ = nullptr;
331     sptr<CodecHDI::ICodecComponentManager> compMgr_ = nullptr;
332 
333     std::shared_ptr<MediaCodecCallback> callback_;
334     PixelFmt configuredFmt_{};
335     BufferRequestConfig requestCfg_{};
336     std::shared_ptr<Format> configFormat_;
337     std::shared_ptr<Format> inputFormat_;
338     std::shared_ptr<Format> outputFormat_;
339 
340     std::vector<BufferInfo> inputBufferPool_;
341     std::vector<BufferInfo> outputBufferPool_;
342     bool isBufferCirculating_ = false;
343     bool inputPortEos_ = false;
344     bool outputPortEos_ = false;
345     bool gotFirstInput_ = false;
346     bool gotFirstOutput_ = false;
347     bool outPortHasChanged_ = false;
348 
349     // VRR
350 #ifdef USE_VIDEO_PROCESSING_ENGINE
351     bool isVrrInitialized_ = false;
VrrPrediction(BufferInfo & info)352     virtual int32_t VrrPrediction(BufferInfo &info) { return AVCS_ERR_UNSUPPORT; }
353 #endif
354 
355     struct TotalCntAndCost {
356         uint64_t totalCnt = 0;
357         uint64_t totalCostUs = 0;
358     };
359 
360     // whole lift time
361     uint64_t inTotalCnt_ = 0;
362     TotalCntAndCost outRecord_;
363     std::unordered_map<int64_t, std::chrono::time_point<std::chrono::steady_clock>> inTimeMap_;
364 
365     // normal: every 200 frames, debug: whole life time
366     static constexpr uint64_t PRINT_PER_FRAME = 200;
367     std::array<TotalCntAndCost, OWNER_CNT> inputHoldTimeRecord_;
368     std::array<TotalCntAndCost, OWNER_CNT> outputHoldTimeRecord_;
369     std::chrono::time_point<std::chrono::steady_clock> firstInTime_;
370     std::chrono::time_point<std::chrono::steady_clock> firstOutTime_;
371 
372     // used when buffer circulation stoped
373     static constexpr char KEY_LAST_OWNER_CHANGE_TIME[] = "lastOwnerChangeTime";
374     std::chrono::time_point<std::chrono::steady_clock> lastOwnerChangeTime_;
375     uint32_t circulateWarnPrintedTimes_ = 0;
376     static constexpr uint32_t MAX_CIRCULATE_WARN_TIMES = 3;
377 
378     std::array<int, HCodec::OWNER_CNT> inputOwner_ {};
379     std::array<std::string, HCodec::OWNER_CNT> inputOwnerStr_ {};
380     std::array<int, HCodec::OWNER_CNT> outputOwner_ {};
381     std::array<std::string, HCodec::OWNER_CNT> outputOwnerStr_ {};
382 
383     static constexpr char BUFFER_ID[] = "buffer-id";
384     static constexpr uint32_t WAIT_FENCE_MS = 1000;
385     static constexpr uint32_t WARN_FENCE_MS = 30;
386     static constexpr uint32_t STRIDE_ALIGNMENT = 32;
387     static constexpr double FRAME_RATE_COEFFICIENT = 65536.0;
388 
389 private:
390     struct BaseState : State {
391     protected:
392         BaseState(HCodec *codec, const std::string &stateName,
393                   BufferOperationMode inputMode = KEEP_BUFFER, BufferOperationMode outputMode = KEEP_BUFFER)
394             : State(stateName), codec_(codec), inputMode_(inputMode), outputMode_(outputMode) {}
395         void OnMsgReceived(const MsgInfo &info) override;
396         void ReplyErrorCode(MsgId id, int32_t err);
397         void OnCodecEvent(const MsgInfo &info);
398         virtual void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2);
399         void OnGetFormat(const MsgInfo &info);
400         virtual void OnShutDown(const MsgInfo &info) = 0;
401         virtual void OnCheckIfStuck(const MsgInfo &info);
402         void OnForceShutDown(const MsgInfo &info);
OnStateExitedBaseState403         void OnStateExited() override { codec_->stateGeneration_++; }
404         void OnSetParameters(const MsgInfo &info);
405 
406     protected:
407         HCodec *codec_;
408         BufferOperationMode inputMode_;
409         BufferOperationMode outputMode_;
410     };
411 
412     struct UninitializedState : BaseState {
UninitializedStateUninitializedState413         explicit UninitializedState(HCodec *codec) : BaseState(codec, "Uninitialized") {}
414     private:
415         void OnStateEntered() override;
416         void OnMsgReceived(const MsgInfo &info) override;
417         void OnShutDown(const MsgInfo &info) override;
418     };
419 
420     struct InitializedState : BaseState {
InitializedStateInitializedState421         explicit InitializedState(HCodec *codec) : BaseState(codec, "Initialized") {}
422     private:
423         void OnStateEntered() override;
424         void ProcessShutDownFromRunning();
425         void OnMsgReceived(const MsgInfo &info) override;
426         void OnSetCallBack(const MsgInfo &info);
427         void OnConfigure(const MsgInfo &info);
428         void OnStart(const MsgInfo &info);
429         void OnShutDown(const MsgInfo &info) override;
430     };
431 
432     struct StartingState : BaseState {
StartingStateStartingState433         explicit StartingState(HCodec *codec) : BaseState(codec, "Starting") {}
434     private:
435         void OnStateEntered() override;
436         void OnStateExited() override;
437         void OnMsgReceived(const MsgInfo &info) override;
438         int32_t AllocateBuffers();
439         void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override;
440         void OnShutDown(const MsgInfo &info) override;
441         void ReplyStartMsg(int32_t errCode);
442         bool hasError_ = false;
443     };
444 
445     struct RunningState : BaseState {
RunningStateRunningState446         explicit RunningState(HCodec *codec) : BaseState(codec, "Running", RESUBMIT_BUFFER, RESUBMIT_BUFFER) {}
447     private:
448         void OnStateEntered() override;
449         void OnMsgReceived(const MsgInfo &info) override;
450         void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override;
451         void OnShutDown(const MsgInfo &info) override;
452         void OnFlush(const MsgInfo &info);
453     };
454 
455     struct OutputPortChangedState : BaseState {
OutputPortChangedStateOutputPortChangedState456         explicit OutputPortChangedState(HCodec *codec)
457             : BaseState(codec, "OutputPortChanged", RESUBMIT_BUFFER, FREE_BUFFER) {}
458     private:
459         void OnStateEntered() override;
460         void OnMsgReceived(const MsgInfo &info) override;
461         void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override;
462         void OnShutDown(const MsgInfo &info) override;
463         void HandleOutputPortDisabled();
464         void HandleOutputPortEnabled();
465         void OnFlush(const MsgInfo &info);
466         void OnCheckIfStuck(const MsgInfo &info) override;
467     };
468 
469     struct FlushingState : BaseState {
FlushingStateFlushingState470         explicit FlushingState(HCodec *codec) : BaseState(codec, "Flushing") {}
471     private:
472         void OnStateEntered() override;
473         void OnMsgReceived(const MsgInfo &info) override;
474         void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override;
475         void OnShutDown(const MsgInfo &info) override;
476         void ChangeStateIfWeOwnAllBuffers();
477         bool IsFlushCompleteOnAllPorts();
478         int32_t UpdateFlushStatusOnPorts(uint32_t data1, uint32_t data2);
479         bool flushCompleteFlag_[2] {false, false};
480     };
481 
482     struct StoppingState : BaseState {
StoppingStateStoppingState483         explicit StoppingState(HCodec *codec) : BaseState(codec, "Stopping"),
484             omxNodeInIdleState_(false),
485             omxNodeIsChangingToLoadedState_(false) {}
486     private:
487         void OnStateEntered() override;
488         void OnMsgReceived(const MsgInfo &info) override;
489         void OnCodecEvent(CodecHDI::CodecEventType event, uint32_t data1, uint32_t data2) override;
490         void OnShutDown(const MsgInfo &info) override;
491         void ChangeStateIfWeOwnAllBuffers();
492         void ChangeOmxNodeToLoadedState(bool forceToFreeBuffer);
493         bool omxNodeInIdleState_;
494         bool omxNodeIsChangingToLoadedState_;
495     };
496 
497     class HdiCallback : public CodecHDI::ICodecCallback {
498     public:
HdiCallback(std::weak_ptr<HCodec> codec)499         explicit HdiCallback(std::weak_ptr<HCodec> codec) : codec_(codec) { }
500         virtual ~HdiCallback() = default;
501         int32_t EventHandler(CodecHDI::CodecEventType event,
502                              const CodecHDI::EventInfo& info);
503         int32_t EmptyBufferDone(int64_t appData, const CodecHDI::OmxCodecBuffer& buffer);
504         int32_t FillBufferDone(int64_t appData, const CodecHDI::OmxCodecBuffer& buffer);
505     private:
506         std::weak_ptr<HCodec> codec_;
507     };
508 
509 private:
510     int32_t DoSyncCall(MsgWhat msgType, std::function<void(ParamSP)> oper);
511     int32_t DoSyncCallAndGetReply(MsgWhat msgType, std::function<void(ParamSP)> oper, ParamSP &reply);
512     void PrintCaller();
513     int32_t OnAllocateComponent();
514     void ReleaseComponent();
515     void CleanUpOmxNode();
516     void ChangeOmxToTargetState(CodecHDI::CodecStateType &state,
517                                 CodecHDI::CodecStateType targetState);
518     bool RollOmxBackToLoaded();
519 
520     int32_t ForceShutdown(int32_t generation, bool isNeedNotifyCaller);
521     void SignalError(AVCodecErrorType errorType, int32_t errorCode);
522     void DeferMessage(const MsgInfo &info);
523     void ProcessDeferredMessages();
524     void ReplyToSyncMsgLater(const MsgInfo& msg);
525     bool GetFirstSyncMsgToReply(MsgInfo& msg);
526 
527 private:
528     static constexpr size_t MAX_HCODEC_BUFFER_SIZE = 8192 * 4096 * 4; // 8K RGBA
529     static constexpr uint32_t THREE_SECONDS_IN_US = 3'000'000;
530     static constexpr uint32_t ONE_SECONDS_IN_US = 1'000'000;
531     static constexpr uint32_t FIVE_SECONDS_IN_MS = 5'000;
532 
533     std::shared_ptr<UninitializedState> uninitializedState_;
534     std::shared_ptr<InitializedState> initializedState_;
535     std::shared_ptr<StartingState> startingState_;
536     std::shared_ptr<RunningState> runningState_;
537     std::shared_ptr<OutputPortChangedState> outputPortChangedState_;
538     std::shared_ptr<FlushingState> flushingState_;
539     std::shared_ptr<StoppingState> stoppingState_;
540 
541     int32_t stateGeneration_ = 0;
542     bool isShutDownFromRunning_ = false;
543     bool notifyCallerAfterShutdownComplete_ = false;
544     bool keepComponentAllocated_ = false;
545     bool hasFatalError_ = false;
546     std::list<MsgInfo> deferredQueue_;
547     std::map<MsgType, std::queue<std::pair<MsgId, ParamSP>>> syncMsgToReply_;
548 }; // class HCodec
549 } // namespace OHOS::MediaAVCodec
550 #endif // HCODEC_HCODEC_H
551