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