• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef MEDIACTSNATIVE_NATIVE_CODEC_TEST_BASE_H
18 #define MEDIACTSNATIVE_NATIVE_CODEC_TEST_BASE_H
19 
20 #include <media/NdkMediaCodec.h>
21 #include <zlib.h>
22 
23 #include <cmath>
24 #include <cstdint>
25 #include <list>
26 #include <mutex>
27 #include <vector>
28 
29 #include "NativeMediaCommon.h"
30 
31 #define RETURN_IF_FAIL(status, str)                                          \
32     {                                                                        \
33         media_status_t val = (status);                                       \
34         if (AMEDIA_OK != val) {                                              \
35             std::string msg = StringFormat("%s with error %d \n", str, val); \
36             ALOGE("%s", msg.c_str());                                        \
37             mErrorLogs.append((msg));                                        \
38             return false;                                                    \
39         }                                                                    \
40     }
41 
42 #define RETURN_IF_TRUE(cond, msg)              \
43     if ((cond)) {                              \
44         ALOGE("%s", (msg).c_str());            \
45         mErrorLogs.append((msg)).append("\n"); \
46         return false;                          \
47     }
48 
49 #define RETURN_IF_FALSE(cond, msg)             \
50     if (!(cond)) {                             \
51         ALOGE("%s", (msg).c_str());            \
52         mErrorLogs.append((msg)).append("\n"); \
53         return false;                          \
54     }
55 
56 #define RETURN_IF_NULL(var, msg)               \
57     if ((var) == nullptr) {                    \
58         ALOGE("%s", (msg).c_str());            \
59         mErrorLogs.append((msg)).append("\n"); \
60         return false;                          \
61     }
62 
63 struct callbackObject {
64     AMediaCodecBufferInfo bufferInfo;
65     int32_t bufferIndex;
66     bool isInput;
67 
callbackObjectcallbackObject68     callbackObject(int32_t index, AMediaCodecBufferInfo* info)
69         : bufferInfo{*info}, bufferIndex{index}, isInput{false} {}
70 
callbackObjectcallbackObject71     callbackObject(int32_t index) : bufferIndex{index}, isInput{true} {}
72 
callbackObjectcallbackObject73     callbackObject() : bufferIndex{-1}, isInput{false} {}
74 };
75 
76 class CodecAsyncHandler {
77   private:
78     std::mutex mMutex;
79     std::condition_variable mCondition;
80     std::list<callbackObject> mCbInputQueue;
81     std::list<callbackObject> mCbOutputQueue;
82     AMediaFormat* mOutFormat;
83     volatile bool mSignalledOutFormatChanged;
84     volatile bool mSignalledError;
85     std::string mErrorMsg;
86 
87   public:
88     CodecAsyncHandler();
89     ~CodecAsyncHandler();
90     void pushToInputList(callbackObject element);
91     void pushToOutputList(callbackObject element);
92     callbackObject getInput();
93     callbackObject getOutput();
94     callbackObject getWork();
95     bool isInputQueueEmpty();
96     void clearQueues();
97     void setOutputFormat(AMediaFormat* format);
98     AMediaFormat* getOutputFormat();
99     bool hasOutputFormatChanged();
100     void setError(bool status, std::string& msg);
101     bool getError() const;
102     void resetContext();
103     std::string getErrorMsg();
104     media_status_t setCallBack(AMediaCodec* codec, bool isCodecInAsyncMode);
105 };
106 
107 class OutputManager {
108   private:
109     std::vector<int64_t> inpPtsArray;
110     std::vector<int64_t> outPtsArray;
111     std::vector<uint8_t> memory;
112     uLong crc32value = 0U;
113     std::string mErrorLogs;
114     std::shared_ptr<std::string> mSharedErrorLogs;
115 
116   public:
117     OutputManager(std::shared_ptr<std::string> log = std::make_shared<std::string>())
mSharedErrorLogs(log)118             : mSharedErrorLogs(log) {}
119 
saveInPTS(int64_t pts)120     void saveInPTS(int64_t pts) {
121         // Add only Unique timeStamp, discarding any duplicate frame / non-display frame
122         if (0 == std::count(inpPtsArray.begin(), inpPtsArray.end(), pts)) {
123             inpPtsArray.push_back(pts);
124         }
125     }
saveOutPTS(int64_t pts)126     void saveOutPTS(int64_t pts) { outPtsArray.push_back(pts); }
127     bool isPtsStrictlyIncreasing(int64_t lastPts);
128     bool isOutPtsListIdenticalToInpPtsList(bool requireSorting);
saveToMemory(uint8_t * buf,AMediaCodecBufferInfo * info)129     void saveToMemory(uint8_t* buf, AMediaCodecBufferInfo* info) {
130         memory.insert(memory.end(), buf, buf + info->size);
131     }
updateChecksum(uint8_t * buf,AMediaCodecBufferInfo * info)132     void updateChecksum(uint8_t* buf, AMediaCodecBufferInfo* info) {
133         updateChecksum(buf, info, 0, 0, 0, 0);
134     }
135 
136     void updateChecksum(uint8_t* buf, AMediaCodecBufferInfo* info, int width, int height,
137                         int stride, int bytesPerSample);
getChecksum()138     uLong getChecksum() { return crc32value; }
reset()139     void reset() {
140         inpPtsArray.clear();
141         outPtsArray.clear();
142         memory.clear();
143         crc32value = 0U;
144         mErrorLogs.clear();
145         mSharedErrorLogs->clear();
146     }
147     bool equalsInterlaced(OutputManager* that);
148     bool equals(OutputManager* that);
149     float getRmsError(uint8_t* refData, int length);
getErrorMsg()150     std::string getErrorMsg() { return mErrorLogs + *mSharedErrorLogs; }
getOutStreamSize()151     int getOutStreamSize() { return memory.size(); }
getSharedErrorLogs()152     std::shared_ptr<std::string> getSharedErrorLogs() { return mSharedErrorLogs; }
153 };
154 
155 class CodecTestBase {
156   protected:
157     const char* mMediaType;
158     bool mIsAudio;
159     bool mIsVideo;
160     CodecAsyncHandler mAsyncHandle;
161     bool mIsCodecInAsyncMode;
162     bool mSawInputEOS;
163     bool mSawOutputEOS;
164     bool mSignalEOSWithLastFrame;
165     int mInputCount;
166     int mOutputCount;
167     int64_t mPrevOutputPts;
168     bool mSignalledOutFormatChanged;
169     AMediaFormat* mOutFormat;
170     int mBytesPerSample;
171 
172     bool mSaveToMem;
173     OutputManager* mOutputBuff;
174     OutputManager* mRefBuff;
175     OutputManager* mTestBuff;
176     OutputManager* mReconfBuff;
177 
178     AMediaCodec* mCodec;
179     std::string mTestEnv;
180     std::string mErrorLogs;
181 
182     CodecTestBase(const char* mediaType);
183     ~CodecTestBase();
184     virtual bool configureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame,
185                                 bool isEncoder);
186     virtual bool flushCodec();
187     bool reConfigureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame,
188                           bool isEncoder);
189     virtual void resetContext(bool isAsync, bool signalEOSWithLastFrame);
190     virtual bool enqueueInput(size_t bufferIndex) = 0;
191     virtual bool dequeueOutput(size_t bufferIndex, AMediaCodecBufferInfo* bufferInfo) = 0;
192     virtual bool isTestStateValid();
193     bool enqueueEOS(size_t bufferIndex);
194     virtual bool doWork(int frameLimit);
195     bool queueEOS();
196     bool waitForAllOutputs();
197     static int getWidth(AMediaFormat* format);
198     static int getHeight(AMediaFormat* format);
199     static bool isFormatSimilar(AMediaFormat* inpFormat, AMediaFormat* outFormat);
hasSeenError()200     bool hasSeenError() { return mAsyncHandle.getError(); }
201   public:
getErrorMsg()202     std::string getErrorMsg() {
203         return mTestEnv +
204                 "###################       Error Details         #####################\n" +
205                 mErrorLogs;
206     }
207 };
208 
209 #endif // MEDIACTSNATIVE_NATIVE_CODEC_TEST_BASE_H
210