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 CHECK_STATUS(status, str) \ 32 { \ 33 media_status_t val = (status); \ 34 if (AMEDIA_OK != val) { \ 35 ALOGE("%s with error %d", (str), val); \ 36 return false; \ 37 } \ 38 } 39 40 #define CHECK_ERR(val, strA, strB, result) \ 41 if ((val)) { \ 42 (result) = false; \ 43 ALOGE("%s %s", (strA), (strB)); \ 44 } 45 46 struct callbackObject { 47 AMediaCodecBufferInfo bufferInfo; 48 int32_t bufferIndex; 49 bool isInput; 50 callbackObjectcallbackObject51 callbackObject(int32_t index, AMediaCodecBufferInfo* info) 52 : bufferInfo{*info}, bufferIndex{index}, isInput{false} {} 53 callbackObjectcallbackObject54 callbackObject(int32_t index) : bufferIndex{index}, isInput{true} {} 55 callbackObjectcallbackObject56 callbackObject() : bufferIndex{-1}, isInput{false} {} 57 }; 58 59 class CodecAsyncHandler { 60 private: 61 std::mutex mMutex; 62 std::condition_variable mCondition; 63 std::list<callbackObject> mCbInputQueue; 64 std::list<callbackObject> mCbOutputQueue; 65 AMediaFormat* mOutFormat; 66 volatile bool mSignalledOutFormatChanged; 67 volatile bool mSignalledError; 68 69 public: 70 CodecAsyncHandler(); 71 ~CodecAsyncHandler(); 72 void pushToInputList(callbackObject element); 73 void pushToOutputList(callbackObject element); 74 callbackObject getInput(); 75 callbackObject getOutput(); 76 callbackObject getWork(); 77 bool isInputQueueEmpty(); 78 void clearQueues(); 79 void setOutputFormat(AMediaFormat* format); 80 AMediaFormat* getOutputFormat(); 81 bool hasOutputFormatChanged(); 82 void setError(bool status); 83 bool getError(); 84 void resetContext(); 85 media_status_t setCallBack(AMediaCodec* codec, bool isCodecInAsyncMode); 86 }; 87 88 class OutputManager { 89 private: 90 std::vector<int64_t> inpPtsArray; 91 std::vector<int64_t> outPtsArray; 92 std::vector<uint8_t> memory; 93 uLong crc32value = 0U; 94 95 public: saveInPTS(int64_t pts)96 void saveInPTS(int64_t pts) { 97 // Add only Unique timeStamp, discarding any duplicate frame / non-display frame 98 if (0 == std::count(inpPtsArray.begin(), inpPtsArray.end(), pts)) { 99 inpPtsArray.push_back(pts); 100 } 101 } saveOutPTS(int64_t pts)102 void saveOutPTS(int64_t pts) { outPtsArray.push_back(pts); } 103 bool isPtsStrictlyIncreasing(int64_t lastPts); 104 bool isOutPtsListIdenticalToInpPtsList(bool requireSorting); saveToMemory(uint8_t * buf,AMediaCodecBufferInfo * info)105 void saveToMemory(uint8_t* buf, AMediaCodecBufferInfo* info) { 106 memory.insert(memory.end(), buf, buf + info->size); 107 } updateChecksum(uint8_t * buf,AMediaCodecBufferInfo * info)108 void updateChecksum(uint8_t* buf, AMediaCodecBufferInfo* info) { 109 updateChecksum(buf, info, 0, 0, 0, 0); 110 } 111 112 void updateChecksum(uint8_t* buf, AMediaCodecBufferInfo* info, int width, int height, 113 int stride, int bytesPerSample); getChecksum()114 uLong getChecksum() { return crc32value; } reset()115 void reset() { 116 inpPtsArray.clear(); 117 outPtsArray.clear(); 118 memory.clear(); 119 crc32value = 0U; 120 } 121 bool equals(const OutputManager* that); 122 float getRmsError(uint8_t* refData, int length); getOutStreamSize()123 int getOutStreamSize() { return memory.size(); } 124 }; 125 126 class CodecTestBase { 127 protected: 128 const char* mMime; 129 bool mIsAudio; 130 CodecAsyncHandler mAsyncHandle; 131 bool mIsCodecInAsyncMode; 132 bool mSawInputEOS; 133 bool mSawOutputEOS; 134 bool mSignalEOSWithLastFrame; 135 int mInputCount; 136 int mOutputCount; 137 int64_t mPrevOutputPts; 138 bool mSignalledOutFormatChanged; 139 AMediaFormat* mOutFormat; 140 int mBytesPerSample; 141 142 bool mSaveToMem; 143 OutputManager* mOutputBuff; 144 OutputManager mRefBuff; 145 OutputManager mTestBuff; 146 OutputManager mReconfBuff; 147 148 AMediaCodec* mCodec; 149 150 CodecTestBase(const char* mime); 151 ~CodecTestBase(); 152 virtual bool configureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame, 153 bool isEncoder); 154 virtual bool flushCodec(); 155 bool reConfigureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame, 156 bool isEncoder); 157 virtual void resetContext(bool isAsync, bool signalEOSWithLastFrame); 158 virtual bool enqueueInput(size_t bufferIndex) = 0; 159 virtual bool dequeueOutput(size_t bufferIndex, AMediaCodecBufferInfo* bufferInfo) = 0; 160 bool enqueueEOS(size_t bufferIndex); 161 bool doWork(int frameLimit); 162 bool queueEOS(); 163 bool waitForAllOutputs(); 164 int getWidth(AMediaFormat* format); 165 int getHeight(AMediaFormat* format); 166 bool isFormatSimilar(AMediaFormat* inpFormat, AMediaFormat* outFormat); hasSeenError()167 bool hasSeenError() { return mAsyncHandle.getError(); } 168 }; 169 170 #endif // MEDIACTSNATIVE_NATIVE_CODEC_TEST_BASE_H 171