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
36 extern "C" {
37 #endif
38 #include "libavformat/avformat.h"
39 #include "libavutil/opt.h"
40 #ifdef __cplusplus
41 }
42 #endif
43 
44 namespace 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