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