1/*
2 * Copyright (C) 2022 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 AVDECODER_DEMO_COMMON_H
17#define AVDECODER_DEMO_COMMON_H
18
19#include <iostream>
20#include <atomic>
21#include <fstream>
22#include <queue>
23#include <string>
24#include <vector>
25#include <thread>
26#include <sys/time.h>
27#include "securec.h"
28#include "nocopyable.h"
29#include "media_description.h"
30#include "avcodec_audio_common.h"
31#include "native_avcodec_audioencoder.h"
32#include "avcodec_audio_channel_layout.h"
33#include "avcodec_audio_encoder.h"
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38#include "libavformat/avformat.h"
39#include "libavutil/opt.h"
40#ifdef __cplusplus
41}
42#endif
43
44namespace OHOS {
45    namespace MediaAVCodec {
46        extern void OnError(OH_AVCodec* codec, int32_t errorCode, void* userData);
47        extern void OnOutputFormatChanged(OH_AVCodec* codec, OH_AVFormat* format, void* userData);
48        extern void OnInputBufferAvailable(OH_AVCodec* codec, uint32_t index, OH_AVMemory* data, void* userData);
49        extern void OnOutputBufferAvailable(OH_AVCodec* codec, uint32_t index,
50            OH_AVMemory* data, OH_AVCodecBufferAttr* attr, void* userData);
51
52        constexpr uint32_t FRAME_DURATION_US = 33000;
53        constexpr int32_t INPUT_FRAME_BYTES = 2 * 1024 * 4;
54        constexpr int32_t COMMON_FLAC_NUM = 576;
55        constexpr int32_t S16_BITS_PER_SAMPLE = 2;
56        constexpr int32_t S32_BITS_PER_SAMPLE = 4;
57        constexpr int32_t UNKNOWN_CHANNEL = 0;
58
59        constexpr int32_t AAC_FRAME_SIZE = 1024;
60        constexpr int32_t AAC_DEFAULT_BYTES_PER_SAMPLE = 4;
61
62        constexpr double DEFAULT_TIME_NUM = 1000000.0;
63        constexpr uint32_t ERROR_INDEX = 100;
64
65        typedef enum MyTimer {
66            TIMER_NONE = 0,
67            TIMER_INPUT = 1,
68            TIMER_FREEOUTPUT = 2,
69            TIMER_GETOUTPUTDESCRIPTION = 3
70        } MyTimer;
71
72        class AEncSignal {
73        public:
74            std::mutex inMutex_;
75            std::mutex outMutex_;
76            std::condition_variable inCond_;
77            std::condition_variable outCond_;
78            std::queue<uint32_t> inQueue_;
79            std::queue<uint32_t> outQueue_;
80            std::queue<OH_AVMemory*> inBufferQueue_;
81            std::queue<OH_AVMemory*> outBufferQueue_;
82            std::queue<OH_AVCodecBufferAttr> attrQueue_;
83            std::queue<AVCodecBufferInfo> infoQueue_;
84            std::queue<AVCodecBufferFlag> flagQueue_;
85            std::queue<std::shared_ptr<AVSharedMemory>> inInnerBufQueue_;
86            std::queue<std::shared_ptr<AVSharedMemory>> outInnerBufQueue_;
87        };
88        class InnerAEnDemoCallback : public AVCodecCallback, public NoCopyable {
89        public:
90            explicit InnerAEnDemoCallback(std::shared_ptr<AEncSignal> signal);
91            ~InnerAEnDemoCallback() = default;
92
93            void OnError(AVCodecErrorType errorType, int32_t errorCode) override;
94            void OnOutputFormatChanged(const Format& format) override;
95            void OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer) override;
96            void OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag,
97                std::shared_ptr<AVSharedMemory> buffer) override;
98        private:
99            std::shared_ptr<AEncSignal> innersignal_;
100        };
101
102        class AudioEncoderDemo : public NoCopyable {
103        public:
104            AudioEncoderDemo();
105            ~AudioEncoderDemo();
106
107            // native api
108            OH_AVCodec* NativeCreateByMime(const char* mime);
109            OH_AVCodec* NativeCreateByName(const char* name);
110            OH_AVErrCode NativeDestroy(OH_AVCodec *codec);
111            OH_AVErrCode NativeSetCallback(OH_AVCodec* codec, OH_AVCodecAsyncCallback callback);
112            OH_AVErrCode NativeConfigure(OH_AVCodec* codec, OH_AVFormat* format);
113            OH_AVErrCode NativePrepare(OH_AVCodec* codec);
114            OH_AVErrCode NativeStart(OH_AVCodec* codec);
115            OH_AVErrCode NativeStop(OH_AVCodec* codec);
116            OH_AVErrCode NativeFlush(OH_AVCodec* codec);
117            OH_AVErrCode NativeReset(OH_AVCodec* codec);
118            OH_AVFormat* NativeGetOutputDescription(OH_AVCodec* codec);
119            OH_AVErrCode NativeSetParameter(OH_AVCodec* codec, OH_AVFormat* format);
120            OH_AVErrCode NativePushInputData(OH_AVCodec* codec, uint32_t index, OH_AVCodecBufferAttr attr);
121            OH_AVErrCode NativeFreeOutputData(OH_AVCodec* codec, uint32_t index);
122            OH_AVErrCode NativeIsValid(OH_AVCodec* codec, bool* isVaild);
123
124            void stopThread();
125            void updateInputData();
126            void updateOutputData();
127
128            void setTimerFlag(int32_t flag);
129
130            uint32_t NativeGetInputIndex();
131            uint8_t* NativeGetInputBuf();
132            uint32_t NativeGetOutputIndex();
133            void HandleEOS(const uint32_t& index);
134
135            void NativePushInput(uint32_t index);
136            void NativeGetDescription();
137            void NativeWriteOutput(std::ofstream& outputFile, uint32_t index,
138                OH_AVCodecBufferAttr attr, OH_AVMemory* data);
139            void NativeInputFunc();
140            void NativeOutputFunc();
141            void NativeCreateToStart(const char* name, OH_AVFormat* format);
142            void NativeStopAndClear();
143
144            void NativeRunCase(std::string inputFile, std::string outputFile,
145                const char* name, OH_AVFormat* format);
146            void NativeRunCaseWithoutCreate(OH_AVCodec* handle, std::string inputFile,
147                std::string outputFile, OH_AVFormat* format, const char* name, bool needConfig);
148            void NativeRunCasePerformance(std::string inputFile, std::string outputFile,
149                const char* name, OH_AVFormat* format);
150            void NativeRunCaseFlush(std::string inputFile, std::string outputFileFirst,
151                std::string outputFileSecond, const char* name, OH_AVFormat* format);
152            void NativeRunCaseReset(std::string inputFile, std::string outputFileFirst,
153                std::string outputFileSecond, const char* name, OH_AVFormat* format);
154            OH_AVFormat* NativeRunCaseGetOutputDescription(std::string inputFile,
155                std::string outputFile, const char* name, OH_AVFormat* format);
156
157            // for test
158            void TestOutputFunc();
159            void TestRunCase(std::string inputFile, std::string outputFile, const char* name, OH_AVFormat* format);
160
161            // Inner api
162            int32_t InnerCreateByMime(const std::string& mime);
163            int32_t InnerCreateByName(const std::string& name);
164            int32_t InnerConfigure(const Format& format);
165            int32_t InnerPrepare();
166            int32_t InnerStart();
167            int32_t InnerStop();
168            int32_t InnerFlush();
169            int32_t InnerReset();
170            int32_t InnerRelease();
171            int32_t InnerQueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag);
172
173            int32_t InnerGetOutputFormat(Format& format);
174            int32_t InnerReleaseOutputBuffer(uint32_t index);
175            int32_t InnerSetParameter(const Format& format);
176            int32_t InnerSetCallback(const std::shared_ptr<AVCodecCallback>& callback);
177            int32_t InnerDestroy();
178            void InnerInputFunc();
179            void InnerOutputFunc();
180            void InnerRunCase(std::string inputFile, std::string outputFile,
181                const std::string& name, Format& format);
182            void InnerRunCaseFlush(std::string inputFile, std::string outputFileFirst,
183                std::string outputFileSecond, const std::string& name, Format& format);
184
185            void InnerCreateToStart(const std::string& name, Format& format);
186            void InnerStopAndClear();
187            void InnerRunCaseReset(std::string inputFile, std::string outputFileFirst,
188                std::string outputFileSecond, const std::string& name, Format& format);
189
190            std::shared_ptr<AEncSignal> getSignal();
191            void InnerStopThread();
192            void InnerHandleEOS(const uint32_t& index);
193            uint32_t InnerGetInputIndex();
194            uint32_t InnerGetOutputIndex();
195            int32_t InnerStartWithThread();
196            void InnerUpdateInputData();
197            void InnerUpdateOutputData();
198
199        private:
200            std::atomic<bool> isRunning_ = false;
201            std::ifstream inputFile_;
202            std::unique_ptr<std::thread> inputLoop_;
203            std::unique_ptr<std::thread> outputLoop_;
204            OH_AVCodec* audioEnc_;
205            AEncSignal* signal_;
206            struct OH_AVCodecAsyncCallback cb_;
207            bool isFirstFrame_ = true;
208
209            std::unique_ptr<std::ifstream> testFile_;
210            std::shared_ptr<AVCodecAudioEncoder> inneraudioEnc_;
211            std::shared_ptr<AEncSignal> innersignal_;
212            std::shared_ptr<InnerAEnDemoCallback> innercb_;
213            uint32_t frameCount_ = 0;
214            int64_t timeStamp_ = 0;
215
216            std::queue<uint32_t> inIndexQueue_;
217            std::queue<uint8_t*> inBufQueue_;
218            std::queue<uint32_t> outIndexQueue_;
219
220            std::string outputFilePath;
221            std::string inputFilePath;
222            OH_AVFormat* curFormat = nullptr;
223            bool isGetOutputDescription = false;
224
225            int32_t timerFlag = 0;
226            int32_t runTimes = 0;
227            double totalTime = 0.0;
228            double otherTime = 0.0;
229            struct timeval startTime, endTime;
230            struct timeval start, end;
231            struct timeval inputStart, inputEnd;
232            struct timeval outputStart, outputEnd;
233            int32_t inputBufSize = INPUT_FRAME_BYTES;
234        };
235    }
236}
237#endif // AVDECODER_DEMO_COMMON_H