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_TESTER_COMMON_H
17 #define HCODEC_TESTER_COMMON_H
18 
19 #include <fstream>
20 #include <mutex>
21 #include <condition_variable>
22 #include <memory>
23 #include "surface.h"
24 #include "wm/window.h"  // foundation/window/window_manager/interfaces/innerkits/
25 #include "native_avbuffer.h" // foundation/multimedia/media_foundation/interface/kits/c
26 #include "buffer/avbuffer.h" // foundation/multimedia/media_foundation/interface/inner_api
27 #include "native_avcodec_base.h" // foundation/multimedia/av_codec/interfaces/kits/c/
28 #include "command_parser.h"
29 #include "start_code_detector.h"
30 #include "test_utils.h"
31 
32 namespace OHOS::MediaAVCodec {
33 struct Span {
34     uint8_t* va;
35     size_t capacity;
36 };
37 
38 struct ImgBuf : Span {
39     GraphicPixelFormat fmt;
40     uint32_t dispW;
41     uint32_t dispH;
42     uint32_t byteStride;
43 };
44 
45 struct BufInfo : ImgBuf {
46     uint32_t idx;
47     OH_AVCodecBufferAttr attr;
48     OH_AVMemory* mem = nullptr;
49     OH_AVBuffer* cavbuf = nullptr;
50     std::shared_ptr<Media::AVBuffer> avbuf;
51     sptr<SurfaceBuffer> surfaceBuf;
52 };
53 
54 struct TesterCommon {
55     static bool Run(const CommandOpt &opt);
56     bool RunOnce();
57 
58 protected:
59     static std::shared_ptr<TesterCommon> Create(const CommandOpt &opt);
TesterCommonTesterCommon60     explicit TesterCommon(const CommandOpt &opt) : opt_(opt) {}
61     virtual ~TesterCommon() = default;
62     static int64_t GetNowUs();
63     virtual bool Create() = 0;
64     virtual bool SetCallback() = 0;
65     virtual bool GetInputFormat() = 0;
66     virtual bool GetOutputFormat() = 0;
67     virtual bool Start() = 0;
68     void EncoderInputLoop();
69     void DecoderInputLoop();
70     void OutputLoop();
71     void BeforeQueueInput(OH_AVCodecBufferAttr& attr);
72     void AfterGotOutput(const OH_AVCodecBufferAttr& attr);
73     virtual bool WaitForInput(BufInfo& buf) = 0;
74     virtual bool WaitForOutput(BufInfo& buf) = 0;
75     virtual bool ReturnInput(const BufInfo& buf) = 0;
76     virtual bool ReturnOutput(uint32_t idx) = 0;
77     virtual bool Flush() = 0;
78     virtual void ClearAllBuffer() = 0;
79     virtual bool Stop() = 0;
80     virtual bool Release() = 0;
81     static std::string GetCodecMime(const CodeType& type);
82 
83     CommandOpt opt_;
84     std::ifstream ifs_;
85 
86     std::mutex inputMtx_;
87     std::condition_variable inputCond_;
88     uint32_t currInputCnt_ = 0;
89 
90     std::mutex outputMtx_;
91     std::condition_variable outputCond_;
92 
93     uint64_t inTotalCnt_ = 0;
94     int64_t firstInTime_ = 0;
95     double inFps_ = 0;
96     uint64_t outTotalCnt_ = 0;
97     int64_t firstOutTime_ = 0;
98     uint64_t totalCost_ = 0;
99 
100     // encoder only
101     bool RunEncoder();
102     virtual bool ConfigureEncoder() = 0;
103     bool UpdateMemberFromResourceParam(const ResourceParams& param);
104     std::shared_ptr<Media::AVBuffer> CreateWaterMarkBuffer();
SetEncoderParameterTesterCommon105     virtual bool SetEncoderParameter(const SetParameterParams& param) { return true; }
SetEncoderPerFrameParamTesterCommon106     virtual bool SetEncoderPerFrameParam(BufInfo& buf, const PerFrameParams& param) { return true; }
107     virtual sptr<Surface> CreateInputSurface() = 0;
108     virtual bool NotifyEos() = 0;
109     virtual bool RequestIDR() = 0;
110     virtual std::optional<uint32_t> GetInputStride() = 0;
111     static bool SurfaceBufferToBufferInfo(BufInfo& buf, sptr<SurfaceBuffer> surfaceBuffer);
112     static bool NativeBufferToBufferInfo(BufInfo& buf, OH_NativeBuffer* nativeBuffer);
113     bool WaitForInputSurfaceBuffer(BufInfo& buf);
114     bool ReturnInputSurfaceBuffer(BufInfo& buf);
115     uint32_t ReadOneFrame(ImgBuf& dstImg);
116     static uint32_t ReadOneFrameYUV420P(std::ifstream& src, ImgBuf& dstImg);
117     static uint32_t ReadOneFrameYUV420SP(std::ifstream& src, ImgBuf& dstImg);
118     static uint32_t ReadOneFrameRGBA(std::ifstream& src, ImgBuf& dstImg);
119     sptr<Surface> producerSurface_;
120     uint32_t w_ = 0;
121     uint32_t h_ = 0;
122     GraphicPixelFormat displayFmt_;
123     static constexpr uint32_t BYTES_PER_PIXEL_RBGA = 4;
124     static constexpr uint32_t SAMPLE_RATIO = 2;
125 
126     // decoder only
127     class Listener : public IBufferConsumerListener {
128     public:
ListenerTesterCommon129         explicit Listener(TesterCommon *test) : tester_(test) {}
130         void OnBufferAvailable() override;
131     private:
132         TesterCommon *tester_;
133     };
134 
135     bool RunDecoder();
136     bool InitDemuxer();
137     sptr<Surface> CreateSurfaceFromWindow();
138     sptr<Surface> CreateSurfaceNormal();
139     virtual bool SetOutputSurface(sptr<Surface> &surface) = 0;
140     void PrepareSeek();
141     bool SeekIfNecessary(); // false means quit loop
142     virtual bool ConfigureDecoder() = 0;
143     int GetNextSample(const Span &dstSpan, size_t &sampleIdx, bool &isCsd); // return filledLen
144     sptr<Surface> surface_; // consumer
145     sptr<OHOS::Rosen::Window> window_;
146     std::shared_ptr<StartCodeDetector> demuxer_;
147     size_t totalSampleCnt_ = 0;
148     size_t currSampleIdx_ = 0;
149     std::list<std::pair<size_t, size_t>> userSeekPos_; // seek from which index to which index
150 
151     static bool RunDecEnc(const CommandOpt &decOpt);
152     void SaveVivid(int64_t pts);
153     void CheckVivid(const BufInfo& buf);
154     static std::mutex vividMtx_;
155     static std::unordered_map<int64_t, std::vector<uint8_t>> vividMap_;
156 };
157 } // namespace OHOS::MediaAVCodec
158 #endif