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