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