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 #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); 110 } 111 void updateChecksum( 112 uint8_t* buf, AMediaCodecBufferInfo* info, int width, int height, int stride); getChecksum()113 uLong getChecksum() { return crc32value; } reset()114 void reset() { 115 inpPtsArray.clear(); 116 outPtsArray.clear(); 117 memory.clear(); 118 crc32value = 0U; 119 } 120 bool equals(const OutputManager* that); 121 float getRmsError(uint8_t* refData, int length); getOutStreamSize()122 int getOutStreamSize() { return memory.size(); } 123 }; 124 125 class CodecTestBase { 126 protected: 127 const char* mMime; 128 bool mIsAudio; 129 CodecAsyncHandler mAsyncHandle; 130 bool mIsCodecInAsyncMode; 131 bool mSawInputEOS; 132 bool mSawOutputEOS; 133 bool mSignalEOSWithLastFrame; 134 int mInputCount; 135 int mOutputCount; 136 int64_t mPrevOutputPts; 137 bool mSignalledOutFormatChanged; 138 AMediaFormat* mOutFormat; 139 140 bool mSaveToMem; 141 OutputManager* mOutputBuff; 142 OutputManager mRefBuff; 143 OutputManager mTestBuff; 144 OutputManager mReconfBuff; 145 146 AMediaCodec* mCodec; 147 148 CodecTestBase(const char* mime); 149 ~CodecTestBase(); 150 virtual bool configureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame, 151 bool isEncoder); 152 virtual bool flushCodec(); 153 bool reConfigureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame, 154 bool isEncoder); 155 virtual void resetContext(bool isAsync, bool signalEOSWithLastFrame); 156 virtual bool enqueueInput(size_t bufferIndex) = 0; 157 virtual bool dequeueOutput(size_t bufferIndex, AMediaCodecBufferInfo* bufferInfo) = 0; 158 bool enqueueEOS(size_t bufferIndex); 159 bool doWork(int frameLimit); 160 bool queueEOS(); 161 bool waitForAllOutputs(); 162 int getWidth(AMediaFormat* format); 163 int getHeight(AMediaFormat* format); 164 bool isFormatSimilar(AMediaFormat* inpFormat, AMediaFormat* outFormat); hasSeenError()165 bool hasSeenError() { return mAsyncHandle.getError(); } 166 }; 167 168 #endif // MEDIACTSNATIVE_NATIVE_CODEC_TEST_BASE_H 169