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