xref: /aosp_15_r20/cts/tests/media/jni/NativeCodecDecoderTestCommon.cpp (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 //#define LOG_NDEBUG 0
18*b7c941bbSAndroid Build Coastguard Worker #define LOG_TAG "NativeCodecDecoderTestCommon"
19*b7c941bbSAndroid Build Coastguard Worker #include <log/log.h>
20*b7c941bbSAndroid Build Coastguard Worker 
21*b7c941bbSAndroid Build Coastguard Worker #include <android/native_window_jni.h>
22*b7c941bbSAndroid Build Coastguard Worker #include <jni.h>
23*b7c941bbSAndroid Build Coastguard Worker #include <media/NdkMediaExtractor.h>
24*b7c941bbSAndroid Build Coastguard Worker #include <sys/stat.h>
25*b7c941bbSAndroid Build Coastguard Worker 
26*b7c941bbSAndroid Build Coastguard Worker #include <array>
27*b7c941bbSAndroid Build Coastguard Worker #include <fstream>
28*b7c941bbSAndroid Build Coastguard Worker #include <string>
29*b7c941bbSAndroid Build Coastguard Worker 
30*b7c941bbSAndroid Build Coastguard Worker #include "NativeCodecDecoderTestCommon.h"
31*b7c941bbSAndroid Build Coastguard Worker #include "NativeCodecTestBase.h"
32*b7c941bbSAndroid Build Coastguard Worker #include "NativeMediaCommon.h"
33*b7c941bbSAndroid Build Coastguard Worker 
34*b7c941bbSAndroid Build Coastguard Worker class CodecDecoderTest final : public CodecTestBase {
35*b7c941bbSAndroid Build Coastguard Worker   private:
36*b7c941bbSAndroid Build Coastguard Worker     bool mIsInterlaced;
37*b7c941bbSAndroid Build Coastguard Worker     uint8_t* mRefData;
38*b7c941bbSAndroid Build Coastguard Worker     size_t mRefLength;
39*b7c941bbSAndroid Build Coastguard Worker     AMediaExtractor* mExtractor;
40*b7c941bbSAndroid Build Coastguard Worker     AMediaFormat* mInpDecFormat;
41*b7c941bbSAndroid Build Coastguard Worker     AMediaFormat* mInpDecDupFormat;
42*b7c941bbSAndroid Build Coastguard Worker     std::vector<std::pair<void*, size_t>> mCsdBuffers;
43*b7c941bbSAndroid Build Coastguard Worker     int mCurrCsdIdx;
44*b7c941bbSAndroid Build Coastguard Worker     ANativeWindow* mWindow;
45*b7c941bbSAndroid Build Coastguard Worker 
46*b7c941bbSAndroid Build Coastguard Worker     void setUpAudioReference(const char* refFile);
47*b7c941bbSAndroid Build Coastguard Worker     void deleteReference();
48*b7c941bbSAndroid Build Coastguard Worker     bool setUpExtractor(const char* srcFile, int colorFormat);
49*b7c941bbSAndroid Build Coastguard Worker     void deleteExtractor();
50*b7c941bbSAndroid Build Coastguard Worker     bool configureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame,
51*b7c941bbSAndroid Build Coastguard Worker                         bool isEncoder) override;
52*b7c941bbSAndroid Build Coastguard Worker     bool enqueueInput(size_t bufferIndex) override;
53*b7c941bbSAndroid Build Coastguard Worker     bool dequeueOutput(size_t bufferIndex, AMediaCodecBufferInfo* bufferInfo) override;
54*b7c941bbSAndroid Build Coastguard Worker     bool isTestStateValid() override;
55*b7c941bbSAndroid Build Coastguard Worker     bool isOutputFormatOk(AMediaFormat* configFormat);
56*b7c941bbSAndroid Build Coastguard Worker     bool queueCodecConfig();
57*b7c941bbSAndroid Build Coastguard Worker     bool enqueueCodecConfig(int32_t bufferIndex);
58*b7c941bbSAndroid Build Coastguard Worker     bool decodeToMemory(const char* decoder, AMediaFormat* format, int frameLimit,
59*b7c941bbSAndroid Build Coastguard Worker                         OutputManager* ref, int64_t pts, SeekMode mode);
60*b7c941bbSAndroid Build Coastguard Worker 
61*b7c941bbSAndroid Build Coastguard Worker   public:
62*b7c941bbSAndroid Build Coastguard Worker     explicit CodecDecoderTest(const char* mediaType, ANativeWindow* window);
63*b7c941bbSAndroid Build Coastguard Worker     ~CodecDecoderTest();
64*b7c941bbSAndroid Build Coastguard Worker 
65*b7c941bbSAndroid Build Coastguard Worker     bool testSimpleDecode(const char* decoder, const char* testFile, const char* refFile,
66*b7c941bbSAndroid Build Coastguard Worker                           int colorFormat, float rmsError, uLong checksum);
67*b7c941bbSAndroid Build Coastguard Worker     bool testFlush(const char* decoder, const char* testFile, int colorFormat);
68*b7c941bbSAndroid Build Coastguard Worker     bool testOnlyEos(const char* decoder, const char* testFile, int colorFormat);
69*b7c941bbSAndroid Build Coastguard Worker     bool testSimpleDecodeQueueCSD(const char* decoder, const char* testFile, int colorFormat);
70*b7c941bbSAndroid Build Coastguard Worker };
71*b7c941bbSAndroid Build Coastguard Worker 
CodecDecoderTest(const char * mediaType,ANativeWindow * window)72*b7c941bbSAndroid Build Coastguard Worker CodecDecoderTest::CodecDecoderTest(const char* mediaType, ANativeWindow* window)
73*b7c941bbSAndroid Build Coastguard Worker     : CodecTestBase(mediaType),
74*b7c941bbSAndroid Build Coastguard Worker       mRefData(nullptr),
75*b7c941bbSAndroid Build Coastguard Worker       mRefLength(0),
76*b7c941bbSAndroid Build Coastguard Worker       mExtractor(nullptr),
77*b7c941bbSAndroid Build Coastguard Worker       mInpDecFormat(nullptr),
78*b7c941bbSAndroid Build Coastguard Worker       mInpDecDupFormat(nullptr),
79*b7c941bbSAndroid Build Coastguard Worker       mCurrCsdIdx(0),
80*b7c941bbSAndroid Build Coastguard Worker       mWindow{window} {}
81*b7c941bbSAndroid Build Coastguard Worker 
~CodecDecoderTest()82*b7c941bbSAndroid Build Coastguard Worker CodecDecoderTest::~CodecDecoderTest() {
83*b7c941bbSAndroid Build Coastguard Worker     deleteReference();
84*b7c941bbSAndroid Build Coastguard Worker     deleteExtractor();
85*b7c941bbSAndroid Build Coastguard Worker }
86*b7c941bbSAndroid Build Coastguard Worker 
setUpAudioReference(const char * refFile)87*b7c941bbSAndroid Build Coastguard Worker void CodecDecoderTest::setUpAudioReference(const char* refFile) {
88*b7c941bbSAndroid Build Coastguard Worker     FILE* fp = fopen(refFile, "rbe");
89*b7c941bbSAndroid Build Coastguard Worker     struct stat buf {};
90*b7c941bbSAndroid Build Coastguard Worker     if (fp && !fstat(fileno(fp), &buf)) {
91*b7c941bbSAndroid Build Coastguard Worker         deleteReference();
92*b7c941bbSAndroid Build Coastguard Worker         mRefLength = buf.st_size;
93*b7c941bbSAndroid Build Coastguard Worker         mRefData = new uint8_t[mRefLength];
94*b7c941bbSAndroid Build Coastguard Worker         fread(mRefData, sizeof(uint8_t), mRefLength, fp);
95*b7c941bbSAndroid Build Coastguard Worker     } else {
96*b7c941bbSAndroid Build Coastguard Worker         ALOGE("unable to open input file %s", refFile);
97*b7c941bbSAndroid Build Coastguard Worker     }
98*b7c941bbSAndroid Build Coastguard Worker     if (fp) fclose(fp);
99*b7c941bbSAndroid Build Coastguard Worker }
100*b7c941bbSAndroid Build Coastguard Worker 
deleteReference()101*b7c941bbSAndroid Build Coastguard Worker void CodecDecoderTest::deleteReference() {
102*b7c941bbSAndroid Build Coastguard Worker     if (mRefData) {
103*b7c941bbSAndroid Build Coastguard Worker         delete[] mRefData;
104*b7c941bbSAndroid Build Coastguard Worker         mRefData = nullptr;
105*b7c941bbSAndroid Build Coastguard Worker     }
106*b7c941bbSAndroid Build Coastguard Worker     mRefLength = 0;
107*b7c941bbSAndroid Build Coastguard Worker }
108*b7c941bbSAndroid Build Coastguard Worker 
setUpExtractor(const char * srcFile,int colorFormat)109*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::setUpExtractor(const char* srcFile, int colorFormat) {
110*b7c941bbSAndroid Build Coastguard Worker     FILE* fp = fopen(srcFile, "rbe");
111*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_NULL(fp, StringFormat("Unable to open file %s", srcFile))
112*b7c941bbSAndroid Build Coastguard Worker     struct stat buf {};
113*b7c941bbSAndroid Build Coastguard Worker     if (!fstat(fileno(fp), &buf)) {
114*b7c941bbSAndroid Build Coastguard Worker         deleteExtractor();
115*b7c941bbSAndroid Build Coastguard Worker         mExtractor = AMediaExtractor_new();
116*b7c941bbSAndroid Build Coastguard Worker         media_status_t res =
117*b7c941bbSAndroid Build Coastguard Worker                 AMediaExtractor_setDataSourceFd(mExtractor, fileno(fp), 0, buf.st_size);
118*b7c941bbSAndroid Build Coastguard Worker         if (res != AMEDIA_OK) {
119*b7c941bbSAndroid Build Coastguard Worker             deleteExtractor();
120*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_TRUE(true,
121*b7c941bbSAndroid Build Coastguard Worker                            StringFormat("AMediaExtractor_setDataSourceFd failed with error %d",
122*b7c941bbSAndroid Build Coastguard Worker                                         res))
123*b7c941bbSAndroid Build Coastguard Worker         } else {
124*b7c941bbSAndroid Build Coastguard Worker             mBytesPerSample = (colorFormat == COLOR_FormatYUVP010) ? 2 : 1;
125*b7c941bbSAndroid Build Coastguard Worker             for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(mExtractor);
126*b7c941bbSAndroid Build Coastguard Worker                  trackID++) {
127*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat* currFormat = AMediaExtractor_getTrackFormat(mExtractor, trackID);
128*b7c941bbSAndroid Build Coastguard Worker                 const char* mediaType = nullptr;
129*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_getString(currFormat, AMEDIAFORMAT_KEY_MIME, &mediaType);
130*b7c941bbSAndroid Build Coastguard Worker                 if (mediaType && strcmp(mMediaType, mediaType) == 0) {
131*b7c941bbSAndroid Build Coastguard Worker                     AMediaExtractor_selectTrack(mExtractor, trackID);
132*b7c941bbSAndroid Build Coastguard Worker                     if (!mIsAudio) {
133*b7c941bbSAndroid Build Coastguard Worker                         AMediaFormat_setInt32(currFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT,
134*b7c941bbSAndroid Build Coastguard Worker                                               colorFormat);
135*b7c941bbSAndroid Build Coastguard Worker                     }
136*b7c941bbSAndroid Build Coastguard Worker                     mInpDecFormat = currFormat;
137*b7c941bbSAndroid Build Coastguard Worker                     // TODO: determine this from the extractor format when it becomes exposed.
138*b7c941bbSAndroid Build Coastguard Worker                     mIsInterlaced = strstr(srcFile, "_interlaced_") != nullptr;
139*b7c941bbSAndroid Build Coastguard Worker                     break;
140*b7c941bbSAndroid Build Coastguard Worker                 }
141*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_delete(currFormat);
142*b7c941bbSAndroid Build Coastguard Worker             }
143*b7c941bbSAndroid Build Coastguard Worker         }
144*b7c941bbSAndroid Build Coastguard Worker     }
145*b7c941bbSAndroid Build Coastguard Worker     if (fp) fclose(fp);
146*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_NULL(mInpDecFormat,
147*b7c941bbSAndroid Build Coastguard Worker                    StringFormat("No track with media type %s found in file: %s", mMediaType,
148*b7c941bbSAndroid Build Coastguard Worker                                 srcFile))
149*b7c941bbSAndroid Build Coastguard Worker     return true;
150*b7c941bbSAndroid Build Coastguard Worker }
151*b7c941bbSAndroid Build Coastguard Worker 
deleteExtractor()152*b7c941bbSAndroid Build Coastguard Worker void CodecDecoderTest::deleteExtractor() {
153*b7c941bbSAndroid Build Coastguard Worker     if (mExtractor) {
154*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_delete(mExtractor);
155*b7c941bbSAndroid Build Coastguard Worker         mExtractor = nullptr;
156*b7c941bbSAndroid Build Coastguard Worker     }
157*b7c941bbSAndroid Build Coastguard Worker     if (mInpDecFormat) {
158*b7c941bbSAndroid Build Coastguard Worker         AMediaFormat_delete(mInpDecFormat);
159*b7c941bbSAndroid Build Coastguard Worker         mInpDecFormat = nullptr;
160*b7c941bbSAndroid Build Coastguard Worker     }
161*b7c941bbSAndroid Build Coastguard Worker     if (mInpDecDupFormat) {
162*b7c941bbSAndroid Build Coastguard Worker         AMediaFormat_delete(mInpDecDupFormat);
163*b7c941bbSAndroid Build Coastguard Worker         mInpDecDupFormat = nullptr;
164*b7c941bbSAndroid Build Coastguard Worker     }
165*b7c941bbSAndroid Build Coastguard Worker }
166*b7c941bbSAndroid Build Coastguard Worker 
configureCodec(AMediaFormat * format,bool isAsync,bool signalEOSWithLastFrame,bool isEncoder)167*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::configureCodec(AMediaFormat* format, bool isAsync,
168*b7c941bbSAndroid Build Coastguard Worker                                       bool signalEOSWithLastFrame, bool isEncoder) {
169*b7c941bbSAndroid Build Coastguard Worker     resetContext(isAsync, signalEOSWithLastFrame);
170*b7c941bbSAndroid Build Coastguard Worker     mTestEnv = "###################      Test Environment       #####################\n";
171*b7c941bbSAndroid Build Coastguard Worker     {
172*b7c941bbSAndroid Build Coastguard Worker         char* name = nullptr;
173*b7c941bbSAndroid Build Coastguard Worker         media_status_t val = AMediaCodec_getName(mCodec, &name);
174*b7c941bbSAndroid Build Coastguard Worker         if (AMEDIA_OK != val) {
175*b7c941bbSAndroid Build Coastguard Worker             mErrorLogs = StringFormat("%s with error %d \n", "AMediaCodec_getName failed", val);
176*b7c941bbSAndroid Build Coastguard Worker             return false;
177*b7c941bbSAndroid Build Coastguard Worker         }
178*b7c941bbSAndroid Build Coastguard Worker         if (!name) {
179*b7c941bbSAndroid Build Coastguard Worker             mErrorLogs = std::string{"AMediaCodec_getName returned null"};
180*b7c941bbSAndroid Build Coastguard Worker             return false;
181*b7c941bbSAndroid Build Coastguard Worker         }
182*b7c941bbSAndroid Build Coastguard Worker         mTestEnv.append(StringFormat("Component name %s \n", name));
183*b7c941bbSAndroid Build Coastguard Worker         AMediaCodec_releaseName(mCodec, name);
184*b7c941bbSAndroid Build Coastguard Worker     }
185*b7c941bbSAndroid Build Coastguard Worker     mTestEnv.append(StringFormat("Format under test :- %s \n", AMediaFormat_toString(format)));
186*b7c941bbSAndroid Build Coastguard Worker     mTestEnv.append(StringFormat("Component operating in :- %s mode \n",
187*b7c941bbSAndroid Build Coastguard Worker                                  (isAsync ? "asynchronous" : "synchronous")));
188*b7c941bbSAndroid Build Coastguard Worker     mTestEnv.append(
189*b7c941bbSAndroid Build Coastguard Worker             StringFormat("Component received input eos :- %s \n",
190*b7c941bbSAndroid Build Coastguard Worker                          (signalEOSWithLastFrame ? "with full buffer" : "with empty buffer")));
191*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FAIL(mAsyncHandle.setCallBack(mCodec, isAsync),
192*b7c941bbSAndroid Build Coastguard Worker                    "AMediaCodec_setAsyncNotifyCallback failed")
193*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FAIL(AMediaCodec_configure(mCodec, format, mWindow, nullptr,
194*b7c941bbSAndroid Build Coastguard Worker                                          isEncoder ? AMEDIACODEC_CONFIGURE_FLAG_ENCODE : 0),
195*b7c941bbSAndroid Build Coastguard Worker                    "AMediaCodec_configure failed")
196*b7c941bbSAndroid Build Coastguard Worker     return true;
197*b7c941bbSAndroid Build Coastguard Worker }
198*b7c941bbSAndroid Build Coastguard Worker 
enqueueCodecConfig(int32_t bufferIndex)199*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::enqueueCodecConfig(int32_t bufferIndex) {
200*b7c941bbSAndroid Build Coastguard Worker     size_t bufSize;
201*b7c941bbSAndroid Build Coastguard Worker     uint8_t* buf = AMediaCodec_getInputBuffer(mCodec, bufferIndex, &bufSize);
202*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_NULL(buf, std::string{"AMediaCodec_getInputBuffer returned nullptr"})
203*b7c941bbSAndroid Build Coastguard Worker     void* csdBuffer = mCsdBuffers[mCurrCsdIdx].first;
204*b7c941bbSAndroid Build Coastguard Worker     size_t csdSize = mCsdBuffers[mCurrCsdIdx].second;
205*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_TRUE(bufSize < csdSize,
206*b7c941bbSAndroid Build Coastguard Worker                    StringFormat("csd exceeds input buffer size, csdSize: %zu bufSize: %zu", csdSize,
207*b7c941bbSAndroid Build Coastguard Worker                                 bufSize))
208*b7c941bbSAndroid Build Coastguard Worker     memcpy((void*)buf, csdBuffer, csdSize);
209*b7c941bbSAndroid Build Coastguard Worker     uint32_t flags = AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG;
210*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FAIL(AMediaCodec_queueInputBuffer(mCodec, bufferIndex, 0, csdSize, 0, flags),
211*b7c941bbSAndroid Build Coastguard Worker                    "AMediaCodec_queueInputBuffer failed")
212*b7c941bbSAndroid Build Coastguard Worker     return !hasSeenError();
213*b7c941bbSAndroid Build Coastguard Worker }
214*b7c941bbSAndroid Build Coastguard Worker 
enqueueInput(size_t bufferIndex)215*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::enqueueInput(size_t bufferIndex) {
216*b7c941bbSAndroid Build Coastguard Worker     if (AMediaExtractor_getSampleSize(mExtractor) < 0) {
217*b7c941bbSAndroid Build Coastguard Worker         return enqueueEOS(bufferIndex);
218*b7c941bbSAndroid Build Coastguard Worker     } else {
219*b7c941bbSAndroid Build Coastguard Worker         uint32_t flags = 0;
220*b7c941bbSAndroid Build Coastguard Worker         size_t bufSize;
221*b7c941bbSAndroid Build Coastguard Worker         uint8_t* buf = AMediaCodec_getInputBuffer(mCodec, bufferIndex, &bufSize);
222*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_NULL(buf, std::string{"AMediaCodec_getInputBuffer returned nullptr"})
223*b7c941bbSAndroid Build Coastguard Worker         ssize_t size = AMediaExtractor_getSampleSize(mExtractor);
224*b7c941bbSAndroid Build Coastguard Worker         int64_t pts = AMediaExtractor_getSampleTime(mExtractor);
225*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_TRUE(size > bufSize,
226*b7c941bbSAndroid Build Coastguard Worker                        StringFormat("extractor sample size exceeds codec input buffer size %zu %zu",
227*b7c941bbSAndroid Build Coastguard Worker                                     size, bufSize))
228*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_TRUE(size != AMediaExtractor_readSampleData(mExtractor, buf, bufSize),
229*b7c941bbSAndroid Build Coastguard Worker                        std::string{"AMediaExtractor_readSampleData failed"})
230*b7c941bbSAndroid Build Coastguard Worker         if (!AMediaExtractor_advance(mExtractor) && mSignalEOSWithLastFrame) {
231*b7c941bbSAndroid Build Coastguard Worker             flags |= AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
232*b7c941bbSAndroid Build Coastguard Worker             mSawInputEOS = true;
233*b7c941bbSAndroid Build Coastguard Worker         }
234*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_FAIL(AMediaCodec_queueInputBuffer(mCodec, bufferIndex, 0, size, pts, flags),
235*b7c941bbSAndroid Build Coastguard Worker                        "AMediaCodec_queueInputBuffer failed")
236*b7c941bbSAndroid Build Coastguard Worker         ALOGV("input: id: %zu  size: %zu  pts: %" PRId64 "  flags: %d", bufferIndex, size, pts,
237*b7c941bbSAndroid Build Coastguard Worker               flags);
238*b7c941bbSAndroid Build Coastguard Worker         if (size > 0) {
239*b7c941bbSAndroid Build Coastguard Worker             mOutputBuff->saveInPTS(pts);
240*b7c941bbSAndroid Build Coastguard Worker             mInputCount++;
241*b7c941bbSAndroid Build Coastguard Worker         }
242*b7c941bbSAndroid Build Coastguard Worker     }
243*b7c941bbSAndroid Build Coastguard Worker     return !hasSeenError();
244*b7c941bbSAndroid Build Coastguard Worker }
245*b7c941bbSAndroid Build Coastguard Worker 
dequeueOutput(size_t bufferIndex,AMediaCodecBufferInfo * info)246*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::dequeueOutput(size_t bufferIndex, AMediaCodecBufferInfo* info) {
247*b7c941bbSAndroid Build Coastguard Worker     if ((info->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) != 0) {
248*b7c941bbSAndroid Build Coastguard Worker         mSawOutputEOS = true;
249*b7c941bbSAndroid Build Coastguard Worker     }
250*b7c941bbSAndroid Build Coastguard Worker     if (info->size > 0 && (info->flags & AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) == 0) {
251*b7c941bbSAndroid Build Coastguard Worker         if (mSaveToMem) {
252*b7c941bbSAndroid Build Coastguard Worker             size_t buffSize;
253*b7c941bbSAndroid Build Coastguard Worker             uint8_t* buf = AMediaCodec_getOutputBuffer(mCodec, bufferIndex, &buffSize);
254*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_NULL(buf, std::string{"AMediaCodec_getOutputBuffer returned nullptr"})
255*b7c941bbSAndroid Build Coastguard Worker             // NdkMediaCodec calls ABuffer::data, which already adds offset
256*b7c941bbSAndroid Build Coastguard Worker             info->offset = 0;
257*b7c941bbSAndroid Build Coastguard Worker             if (mIsAudio) {
258*b7c941bbSAndroid Build Coastguard Worker                 mOutputBuff->saveToMemory(buf, info);
259*b7c941bbSAndroid Build Coastguard Worker                 mOutputBuff->updateChecksum(buf, info);
260*b7c941bbSAndroid Build Coastguard Worker             } else {
261*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat* format =
262*b7c941bbSAndroid Build Coastguard Worker                         mIsCodecInAsyncMode ? mAsyncHandle.getOutputFormat() : mOutFormat;
263*b7c941bbSAndroid Build Coastguard Worker                 int32_t width, height, stride;
264*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_getInt32(format, "width", &width);
265*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_getInt32(format, "height", &height);
266*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_getInt32(format, "stride", &stride);
267*b7c941bbSAndroid Build Coastguard Worker                 mOutputBuff->updateChecksum(buf, info, width, height, stride, mBytesPerSample);
268*b7c941bbSAndroid Build Coastguard Worker             }
269*b7c941bbSAndroid Build Coastguard Worker         }
270*b7c941bbSAndroid Build Coastguard Worker         mOutputBuff->saveOutPTS(info->presentationTimeUs);
271*b7c941bbSAndroid Build Coastguard Worker         mOutputCount++;
272*b7c941bbSAndroid Build Coastguard Worker     }
273*b7c941bbSAndroid Build Coastguard Worker     ALOGV("output: id: %zu  size: %d  pts: %" PRId64 "  flags: %d", bufferIndex, info->size,
274*b7c941bbSAndroid Build Coastguard Worker           info->presentationTimeUs, info->flags);
275*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FAIL(AMediaCodec_releaseOutputBuffer(mCodec, bufferIndex, mWindow != nullptr),
276*b7c941bbSAndroid Build Coastguard Worker                    "AMediaCodec_releaseOutputBuffer failed")
277*b7c941bbSAndroid Build Coastguard Worker     return !hasSeenError();
278*b7c941bbSAndroid Build Coastguard Worker }
279*b7c941bbSAndroid Build Coastguard Worker 
isTestStateValid()280*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::isTestStateValid() {
281*b7c941bbSAndroid Build Coastguard Worker     if (!CodecTestBase::isTestStateValid()) return false;
282*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FALSE(mOutputBuff->isPtsStrictlyIncreasing(mPrevOutputPts),
283*b7c941bbSAndroid Build Coastguard Worker                     std::string{"Output timestamps are not strictly increasing \n"}.append(
284*b7c941bbSAndroid Build Coastguard Worker                             mOutputBuff->getErrorMsg()))
285*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_TRUE(mIsVideo && !mIsInterlaced &&
286*b7c941bbSAndroid Build Coastguard Worker                    !mOutputBuff->isOutPtsListIdenticalToInpPtsList(false),
287*b7c941bbSAndroid Build Coastguard Worker                    std::string{"Input pts list and Output pts list are not identical \n"}.append(
288*b7c941bbSAndroid Build Coastguard Worker                            mOutputBuff->getErrorMsg()))
289*b7c941bbSAndroid Build Coastguard Worker     return true;
290*b7c941bbSAndroid Build Coastguard Worker }
291*b7c941bbSAndroid Build Coastguard Worker 
isOutputFormatOk(AMediaFormat * configFormat)292*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::isOutputFormatOk(AMediaFormat* configFormat) {
293*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_TRUE(mIsCodecInAsyncMode ? !mAsyncHandle.hasOutputFormatChanged()
294*b7c941bbSAndroid Build Coastguard Worker                                        : !mSignalledOutFormatChanged,
295*b7c941bbSAndroid Build Coastguard Worker                    std::string{"Input test file format is not same as default format of component, "
296*b7c941bbSAndroid Build Coastguard Worker                                "but test did not receive INFO_OUTPUT_FORMAT_CHANGED signal.\n"})
297*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_TRUE(!isFormatSimilar(configFormat,
298*b7c941bbSAndroid Build Coastguard Worker                                     mIsCodecInAsyncMode ? mAsyncHandle.getOutputFormat()
299*b7c941bbSAndroid Build Coastguard Worker                                                         : mOutFormat),
300*b7c941bbSAndroid Build Coastguard Worker                    StringFormat("Configured input format and received output format are not "
301*b7c941bbSAndroid Build Coastguard Worker                                 "similar. \nConfigured Input format is :- %s \nReceived Output "
302*b7c941bbSAndroid Build Coastguard Worker                                 "format is :- %s \n",
303*b7c941bbSAndroid Build Coastguard Worker                                 AMediaFormat_toString(configFormat),
304*b7c941bbSAndroid Build Coastguard Worker                                 mIsCodecInAsyncMode ? mAsyncHandle.getOutputFormat() : mOutFormat))
305*b7c941bbSAndroid Build Coastguard Worker     return true;
306*b7c941bbSAndroid Build Coastguard Worker }
307*b7c941bbSAndroid Build Coastguard Worker 
queueCodecConfig()308*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::queueCodecConfig() {
309*b7c941bbSAndroid Build Coastguard Worker     bool isOk = true;
310*b7c941bbSAndroid Build Coastguard Worker     if (mIsCodecInAsyncMode) {
311*b7c941bbSAndroid Build Coastguard Worker         for (mCurrCsdIdx = 0; !hasSeenError() && isOk && mCurrCsdIdx < mCsdBuffers.size();
312*b7c941bbSAndroid Build Coastguard Worker              mCurrCsdIdx++) {
313*b7c941bbSAndroid Build Coastguard Worker             callbackObject element = mAsyncHandle.getInput();
314*b7c941bbSAndroid Build Coastguard Worker             if (element.bufferIndex >= 0) {
315*b7c941bbSAndroid Build Coastguard Worker                 isOk = enqueueCodecConfig(element.bufferIndex);
316*b7c941bbSAndroid Build Coastguard Worker             }
317*b7c941bbSAndroid Build Coastguard Worker         }
318*b7c941bbSAndroid Build Coastguard Worker     } else {
319*b7c941bbSAndroid Build Coastguard Worker         int bufferIndex;
320*b7c941bbSAndroid Build Coastguard Worker         for (mCurrCsdIdx = 0; isOk && mCurrCsdIdx < mCsdBuffers.size(); mCurrCsdIdx++) {
321*b7c941bbSAndroid Build Coastguard Worker             bufferIndex = AMediaCodec_dequeueInputBuffer(mCodec, -1);
322*b7c941bbSAndroid Build Coastguard Worker             if (bufferIndex >= 0) {
323*b7c941bbSAndroid Build Coastguard Worker                 isOk = enqueueCodecConfig(bufferIndex);
324*b7c941bbSAndroid Build Coastguard Worker             } else {
325*b7c941bbSAndroid Build Coastguard Worker                 auto msg = StringFormat("unexpected return value from "
326*b7c941bbSAndroid Build Coastguard Worker                                         "AMediaCodec_dequeueInputBuffer: %d \n",
327*b7c941bbSAndroid Build Coastguard Worker                                         bufferIndex);
328*b7c941bbSAndroid Build Coastguard Worker                 mErrorLogs.append(msg);
329*b7c941bbSAndroid Build Coastguard Worker                 ALOGE("%s", msg.c_str());
330*b7c941bbSAndroid Build Coastguard Worker                 return false;
331*b7c941bbSAndroid Build Coastguard Worker             }
332*b7c941bbSAndroid Build Coastguard Worker         }
333*b7c941bbSAndroid Build Coastguard Worker     }
334*b7c941bbSAndroid Build Coastguard Worker     return !hasSeenError() && isOk;
335*b7c941bbSAndroid Build Coastguard Worker }
336*b7c941bbSAndroid Build Coastguard Worker 
decodeToMemory(const char * decoder,AMediaFormat * format,int frameLimit,OutputManager * ref,int64_t pts,SeekMode mode)337*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::decodeToMemory(const char* decoder, AMediaFormat* format, int frameLimit,
338*b7c941bbSAndroid Build Coastguard Worker                                       OutputManager* ref, int64_t pts, SeekMode mode) {
339*b7c941bbSAndroid Build Coastguard Worker     mSaveToMem = (mWindow == nullptr);
340*b7c941bbSAndroid Build Coastguard Worker     mOutputBuff = ref;
341*b7c941bbSAndroid Build Coastguard Worker     AMediaExtractor_seekTo(mExtractor, pts, mode);
342*b7c941bbSAndroid Build Coastguard Worker     mCodec = AMediaCodec_createCodecByName(decoder);
343*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
344*b7c941bbSAndroid Build Coastguard Worker     if (!configureCodec(format, false, true, false)) return false;
345*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
346*b7c941bbSAndroid Build Coastguard Worker     if (!doWork(frameLimit)) return false;
347*b7c941bbSAndroid Build Coastguard Worker     if (!queueEOS()) return false;
348*b7c941bbSAndroid Build Coastguard Worker     if (!waitForAllOutputs()) return false;
349*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FAIL(AMediaCodec_stop(mCodec), "AMediaCodec_stop failed")
350*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FAIL(AMediaCodec_delete(mCodec), "AMediaCodec_delete failed")
351*b7c941bbSAndroid Build Coastguard Worker     mCodec = nullptr;
352*b7c941bbSAndroid Build Coastguard Worker     mSaveToMem = false;
353*b7c941bbSAndroid Build Coastguard Worker     return !hasSeenError();
354*b7c941bbSAndroid Build Coastguard Worker }
355*b7c941bbSAndroid Build Coastguard Worker 
testSimpleDecode(const char * decoder,const char * testFile,const char * refFile,int colorFormat,float rmsError,uLong checksum)356*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::testSimpleDecode(const char* decoder, const char* testFile,
357*b7c941bbSAndroid Build Coastguard Worker                                         const char* refFile, int colorFormat, float rmsError,
358*b7c941bbSAndroid Build Coastguard Worker                                         uLong checksum) {
359*b7c941bbSAndroid Build Coastguard Worker     if (!setUpExtractor(testFile, colorFormat)) return false;
360*b7c941bbSAndroid Build Coastguard Worker     mSaveToMem = (mWindow == nullptr);
361*b7c941bbSAndroid Build Coastguard Worker     auto ref = mRefBuff;
362*b7c941bbSAndroid Build Coastguard Worker     auto test = mTestBuff;
363*b7c941bbSAndroid Build Coastguard Worker     const bool boolStates[]{true, false};
364*b7c941bbSAndroid Build Coastguard Worker     int loopCounter = 0;
365*b7c941bbSAndroid Build Coastguard Worker     for (auto eosType : boolStates) {
366*b7c941bbSAndroid Build Coastguard Worker         for (auto isAsync : boolStates) {
367*b7c941bbSAndroid Build Coastguard Worker             bool validateFormat = true;
368*b7c941bbSAndroid Build Coastguard Worker             mOutputBuff = loopCounter == 0 ? ref : test;
369*b7c941bbSAndroid Build Coastguard Worker             mOutputBuff->reset();
370*b7c941bbSAndroid Build Coastguard Worker             AMediaExtractor_seekTo(mExtractor, 0, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
371*b7c941bbSAndroid Build Coastguard Worker             /* TODO(b/149981033) */
372*b7c941bbSAndroid Build Coastguard Worker             /* Instead of create and delete codec at every iteration, we would like to create
373*b7c941bbSAndroid Build Coastguard Worker              * once and use it for all iterations and delete before exiting */
374*b7c941bbSAndroid Build Coastguard Worker             mCodec = AMediaCodec_createCodecByName(decoder);
375*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
376*b7c941bbSAndroid Build Coastguard Worker             char* name = nullptr;
377*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_FAIL(AMediaCodec_getName(mCodec, &name), "AMediaCodec_getName failed")
378*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_NULL(name, std::string{"AMediaCodec_getName returned null"})
379*b7c941bbSAndroid Build Coastguard Worker             auto res = strcmp(name, decoder) != 0;
380*b7c941bbSAndroid Build Coastguard Worker             AMediaCodec_releaseName(mCodec, name);
381*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_TRUE(res, StringFormat("Codec name mismatch act/got: %s/%s", decoder, name))
382*b7c941bbSAndroid Build Coastguard Worker             if (!configureCodec(mInpDecFormat, isAsync, eosType, false)) return false;
383*b7c941bbSAndroid Build Coastguard Worker             AMediaFormat* decFormat = AMediaCodec_getOutputFormat(mCodec);
384*b7c941bbSAndroid Build Coastguard Worker             if (isFormatSimilar(mInpDecFormat, decFormat)) {
385*b7c941bbSAndroid Build Coastguard Worker                 ALOGD("Input format is same as default for format for %s", decoder);
386*b7c941bbSAndroid Build Coastguard Worker                 validateFormat = false;
387*b7c941bbSAndroid Build Coastguard Worker             }
388*b7c941bbSAndroid Build Coastguard Worker             AMediaFormat_delete(decFormat);
389*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
390*b7c941bbSAndroid Build Coastguard Worker             if (!doWork(INT32_MAX)) return false;
391*b7c941bbSAndroid Build Coastguard Worker             if (!queueEOS()) return false;
392*b7c941bbSAndroid Build Coastguard Worker             if (!waitForAllOutputs()) return false;
393*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_FAIL(AMediaCodec_stop(mCodec), "AMediaCodec_stop failed")
394*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_FAIL(AMediaCodec_delete(mCodec), "AMediaCodec_delete failed")
395*b7c941bbSAndroid Build Coastguard Worker             mCodec = nullptr;
396*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_TRUE((loopCounter != 0 && !ref->equals(test)),
397*b7c941bbSAndroid Build Coastguard Worker                            std::string{"Decoder output is not consistent across runs \n"}.append(
398*b7c941bbSAndroid Build Coastguard Worker                                    test->getErrorMsg()))
399*b7c941bbSAndroid Build Coastguard Worker             if (validateFormat && !isOutputFormatOk(mInpDecFormat)) {
400*b7c941bbSAndroid Build Coastguard Worker                 return false;
401*b7c941bbSAndroid Build Coastguard Worker             }
402*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_TRUE(checksum != ref->getChecksum(),
403*b7c941bbSAndroid Build Coastguard Worker                            StringFormat("sdk output and ndk output for same configuration is not "
404*b7c941bbSAndroid Build Coastguard Worker                                         "identical. \n sdk buffer output checksum is %lu. \n ndk "
405*b7c941bbSAndroid Build Coastguard Worker                                         "buffer output checksum is %lu. \n",
406*b7c941bbSAndroid Build Coastguard Worker                                         checksum, ref->getChecksum()))
407*b7c941bbSAndroid Build Coastguard Worker             loopCounter++;
408*b7c941bbSAndroid Build Coastguard Worker         }
409*b7c941bbSAndroid Build Coastguard Worker     }
410*b7c941bbSAndroid Build Coastguard Worker     if (mSaveToMem && refFile && rmsError >= 0) {
411*b7c941bbSAndroid Build Coastguard Worker         setUpAudioReference(refFile);
412*b7c941bbSAndroid Build Coastguard Worker         float currError = ref->getRmsError(mRefData, mRefLength);
413*b7c941bbSAndroid Build Coastguard Worker         float errMargin = rmsError * kRmsErrorTolerance;
414*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_TRUE(currError > errMargin,
415*b7c941bbSAndroid Build Coastguard Worker                        StringFormat("rms error too high for file %s, ref/exp/got: %f/%f/%f",
416*b7c941bbSAndroid Build Coastguard Worker                                     testFile, rmsError, errMargin, currError))
417*b7c941bbSAndroid Build Coastguard Worker     }
418*b7c941bbSAndroid Build Coastguard Worker     return true;
419*b7c941bbSAndroid Build Coastguard Worker }
420*b7c941bbSAndroid Build Coastguard Worker 
testFlush(const char * decoder,const char * testFile,int colorFormat)421*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::testFlush(const char* decoder, const char* testFile, int colorFormat) {
422*b7c941bbSAndroid Build Coastguard Worker     if (!setUpExtractor(testFile, colorFormat)) return false;
423*b7c941bbSAndroid Build Coastguard Worker     mCsdBuffers.clear();
424*b7c941bbSAndroid Build Coastguard Worker     for (int i = 0;; i++) {
425*b7c941bbSAndroid Build Coastguard Worker         char csdName[16];
426*b7c941bbSAndroid Build Coastguard Worker         void* csdBuffer;
427*b7c941bbSAndroid Build Coastguard Worker         size_t csdSize;
428*b7c941bbSAndroid Build Coastguard Worker         snprintf(csdName, sizeof(csdName), "csd-%d", i);
429*b7c941bbSAndroid Build Coastguard Worker         if (AMediaFormat_getBuffer(mInpDecFormat, csdName, &csdBuffer, &csdSize)) {
430*b7c941bbSAndroid Build Coastguard Worker             mCsdBuffers.emplace_back(std::make_pair(csdBuffer, csdSize));
431*b7c941bbSAndroid Build Coastguard Worker         } else break;
432*b7c941bbSAndroid Build Coastguard Worker     }
433*b7c941bbSAndroid Build Coastguard Worker     const int64_t pts = 500000;
434*b7c941bbSAndroid Build Coastguard Worker     const SeekMode mode = AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC;
435*b7c941bbSAndroid Build Coastguard Worker     auto ref = mRefBuff;
436*b7c941bbSAndroid Build Coastguard Worker     RETURN_IF_FALSE(decodeToMemory(decoder, mInpDecFormat, INT32_MAX, ref, pts, mode),
437*b7c941bbSAndroid Build Coastguard Worker                     StringFormat("decodeToMemory failed for file: %s codec: %s", testFile, decoder))
438*b7c941bbSAndroid Build Coastguard Worker     auto test = mTestBuff;
439*b7c941bbSAndroid Build Coastguard Worker     mOutputBuff = test;
440*b7c941bbSAndroid Build Coastguard Worker     const bool boolStates[]{true, false};
441*b7c941bbSAndroid Build Coastguard Worker     for (auto isAsync : boolStates) {
442*b7c941bbSAndroid Build Coastguard Worker         if (isAsync) continue;  // TODO(b/147576107)
443*b7c941bbSAndroid Build Coastguard Worker         /* TODO(b/149981033) */
444*b7c941bbSAndroid Build Coastguard Worker         /* Instead of create and delete codec at every iteration, we would like to create
445*b7c941bbSAndroid Build Coastguard Worker          * once and use it for all iterations and delete before exiting */
446*b7c941bbSAndroid Build Coastguard Worker         mCodec = AMediaCodec_createCodecByName(decoder);
447*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
448*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_seekTo(mExtractor, 0, mode);
449*b7c941bbSAndroid Build Coastguard Worker         if (!configureCodec(mInpDecFormat, isAsync, true, false)) return false;
450*b7c941bbSAndroid Build Coastguard Worker         AMediaFormat* defFormat = AMediaCodec_getOutputFormat(mCodec);
451*b7c941bbSAndroid Build Coastguard Worker         bool validateFormat = true;
452*b7c941bbSAndroid Build Coastguard Worker         if (isFormatSimilar(mInpDecFormat, defFormat)) {
453*b7c941bbSAndroid Build Coastguard Worker             ALOGD("Input format is same as default for format for %s", decoder);
454*b7c941bbSAndroid Build Coastguard Worker             validateFormat = false;
455*b7c941bbSAndroid Build Coastguard Worker         }
456*b7c941bbSAndroid Build Coastguard Worker         AMediaFormat_delete(defFormat);
457*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
458*b7c941bbSAndroid Build Coastguard Worker 
459*b7c941bbSAndroid Build Coastguard Worker         /* test flush in running state before queuing input */
460*b7c941bbSAndroid Build Coastguard Worker         if (!flushCodec()) return false;
461*b7c941bbSAndroid Build Coastguard Worker         if (mIsCodecInAsyncMode) {
462*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
463*b7c941bbSAndroid Build Coastguard Worker         }
464*b7c941bbSAndroid Build Coastguard Worker         if (!queueCodecConfig()) return false; /* flushed codec too soon, resubmit csd */
465*b7c941bbSAndroid Build Coastguard Worker         if (!doWork(1)) return false;
466*b7c941bbSAndroid Build Coastguard Worker 
467*b7c941bbSAndroid Build Coastguard Worker         if (!flushCodec()) return false;
468*b7c941bbSAndroid Build Coastguard Worker         if (mIsCodecInAsyncMode) {
469*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
470*b7c941bbSAndroid Build Coastguard Worker         }
471*b7c941bbSAndroid Build Coastguard Worker         if (!queueCodecConfig()) return false; /* flushed codec too soon, resubmit csd */
472*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_seekTo(mExtractor, 0, mode);
473*b7c941bbSAndroid Build Coastguard Worker         test->reset();
474*b7c941bbSAndroid Build Coastguard Worker         if (!doWork(23)) return false;
475*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_TRUE(!mIsInterlaced && !test->isPtsStrictlyIncreasing(mPrevOutputPts),
476*b7c941bbSAndroid Build Coastguard Worker                        std::string{"Output timestamps are not strictly increasing \n"}.append(
477*b7c941bbSAndroid Build Coastguard Worker                                test->getErrorMsg()))
478*b7c941bbSAndroid Build Coastguard Worker 
479*b7c941bbSAndroid Build Coastguard Worker         /* test flush in running state */
480*b7c941bbSAndroid Build Coastguard Worker         if (!flushCodec()) return false;
481*b7c941bbSAndroid Build Coastguard Worker         if (mIsCodecInAsyncMode) {
482*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
483*b7c941bbSAndroid Build Coastguard Worker         }
484*b7c941bbSAndroid Build Coastguard Worker         mSaveToMem = (mWindow == nullptr);
485*b7c941bbSAndroid Build Coastguard Worker         test->reset();
486*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_seekTo(mExtractor, pts, mode);
487*b7c941bbSAndroid Build Coastguard Worker         if (!doWork(INT32_MAX)) return false;
488*b7c941bbSAndroid Build Coastguard Worker         if (!queueEOS()) return false;
489*b7c941bbSAndroid Build Coastguard Worker         if (!waitForAllOutputs()) return false;
490*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_TRUE(isMediaTypeOutputUnAffectedBySeek(mMediaType) && !ref->equals(test),
491*b7c941bbSAndroid Build Coastguard Worker                        std::string{"Decoder output is not consistent across runs \n"}.append(
492*b7c941bbSAndroid Build Coastguard Worker                                test->getErrorMsg()))
493*b7c941bbSAndroid Build Coastguard Worker 
494*b7c941bbSAndroid Build Coastguard Worker         /* test flush in eos state */
495*b7c941bbSAndroid Build Coastguard Worker         if (!flushCodec()) return false;
496*b7c941bbSAndroid Build Coastguard Worker         if (mIsCodecInAsyncMode) {
497*b7c941bbSAndroid Build Coastguard Worker             RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
498*b7c941bbSAndroid Build Coastguard Worker         }
499*b7c941bbSAndroid Build Coastguard Worker         test->reset();
500*b7c941bbSAndroid Build Coastguard Worker         AMediaExtractor_seekTo(mExtractor, pts, mode);
501*b7c941bbSAndroid Build Coastguard Worker         if (!doWork(INT32_MAX)) return false;
502*b7c941bbSAndroid Build Coastguard Worker         if (!queueEOS()) return false;
503*b7c941bbSAndroid Build Coastguard Worker         if (!waitForAllOutputs()) return false;
504*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_FAIL(AMediaCodec_stop(mCodec), "AMediaCodec_stop failed")
505*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_FAIL(AMediaCodec_delete(mCodec), "AMediaCodec_delete failed")
506*b7c941bbSAndroid Build Coastguard Worker         mCodec = nullptr;
507*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_TRUE(isMediaTypeOutputUnAffectedBySeek(mMediaType) && !ref->equals(test),
508*b7c941bbSAndroid Build Coastguard Worker                        std::string{"Decoder output is not consistent across runs \n"}.append(
509*b7c941bbSAndroid Build Coastguard Worker                                test->getErrorMsg()))
510*b7c941bbSAndroid Build Coastguard Worker         if (validateFormat && !isOutputFormatOk(mInpDecFormat)) {
511*b7c941bbSAndroid Build Coastguard Worker             return false;
512*b7c941bbSAndroid Build Coastguard Worker         }
513*b7c941bbSAndroid Build Coastguard Worker         mSaveToMem = false;
514*b7c941bbSAndroid Build Coastguard Worker     }
515*b7c941bbSAndroid Build Coastguard Worker     return true;
516*b7c941bbSAndroid Build Coastguard Worker }
517*b7c941bbSAndroid Build Coastguard Worker 
testOnlyEos(const char * decoder,const char * testFile,int colorFormat)518*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::testOnlyEos(const char* decoder, const char* testFile, int colorFormat) {
519*b7c941bbSAndroid Build Coastguard Worker     if (!setUpExtractor(testFile, colorFormat)) return false;
520*b7c941bbSAndroid Build Coastguard Worker     mSaveToMem = (mWindow == nullptr);
521*b7c941bbSAndroid Build Coastguard Worker     auto ref = mRefBuff;
522*b7c941bbSAndroid Build Coastguard Worker     auto test = mTestBuff;
523*b7c941bbSAndroid Build Coastguard Worker     const bool boolStates[]{true, false};
524*b7c941bbSAndroid Build Coastguard Worker     int loopCounter = 0;
525*b7c941bbSAndroid Build Coastguard Worker     for (auto isAsync : boolStates) {
526*b7c941bbSAndroid Build Coastguard Worker         mOutputBuff = loopCounter == 0 ? ref : test;
527*b7c941bbSAndroid Build Coastguard Worker         mOutputBuff->reset();
528*b7c941bbSAndroid Build Coastguard Worker         /* TODO(b/149981033) */
529*b7c941bbSAndroid Build Coastguard Worker         /* Instead of create and delete codec at every iteration, we would like to create
530*b7c941bbSAndroid Build Coastguard Worker          * once and use it for all iterations and delete before exiting */
531*b7c941bbSAndroid Build Coastguard Worker         mCodec = AMediaCodec_createCodecByName(decoder);
532*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
533*b7c941bbSAndroid Build Coastguard Worker         if (!configureCodec(mInpDecFormat, isAsync, false, false)) return false;
534*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
535*b7c941bbSAndroid Build Coastguard Worker         if (!queueEOS()) return false;
536*b7c941bbSAndroid Build Coastguard Worker         if (!waitForAllOutputs()) return false;
537*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_FAIL(AMediaCodec_stop(mCodec), "AMediaCodec_stop failed")
538*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_FAIL(AMediaCodec_delete(mCodec), "AMediaCodec_delete failed")
539*b7c941bbSAndroid Build Coastguard Worker         mCodec = nullptr;
540*b7c941bbSAndroid Build Coastguard Worker         RETURN_IF_TRUE((loopCounter != 0 && !ref->equals(test)),
541*b7c941bbSAndroid Build Coastguard Worker                        std::string{"Decoder output is not consistent across runs \n"}.append(
542*b7c941bbSAndroid Build Coastguard Worker                                test->getErrorMsg()))
543*b7c941bbSAndroid Build Coastguard Worker         loopCounter++;
544*b7c941bbSAndroid Build Coastguard Worker     }
545*b7c941bbSAndroid Build Coastguard Worker     return true;
546*b7c941bbSAndroid Build Coastguard Worker }
547*b7c941bbSAndroid Build Coastguard Worker 
testSimpleDecodeQueueCSD(const char * decoder,const char * testFile,int colorFormat)548*b7c941bbSAndroid Build Coastguard Worker bool CodecDecoderTest::testSimpleDecodeQueueCSD(const char* decoder, const char* testFile,
549*b7c941bbSAndroid Build Coastguard Worker                                                 int colorFormat) {
550*b7c941bbSAndroid Build Coastguard Worker     if (!setUpExtractor(testFile, colorFormat)) return false;
551*b7c941bbSAndroid Build Coastguard Worker     std::vector<AMediaFormat*> formats;
552*b7c941bbSAndroid Build Coastguard Worker     formats.push_back(mInpDecFormat);
553*b7c941bbSAndroid Build Coastguard Worker     mInpDecDupFormat = AMediaFormat_new();
554*b7c941bbSAndroid Build Coastguard Worker     AMediaFormat_copy(mInpDecDupFormat, mInpDecFormat);
555*b7c941bbSAndroid Build Coastguard Worker     formats.push_back(mInpDecDupFormat);
556*b7c941bbSAndroid Build Coastguard Worker     mCsdBuffers.clear();
557*b7c941bbSAndroid Build Coastguard Worker     for (int i = 0;; i++) {
558*b7c941bbSAndroid Build Coastguard Worker         char csdName[16];
559*b7c941bbSAndroid Build Coastguard Worker         void* csdBuffer;
560*b7c941bbSAndroid Build Coastguard Worker         size_t csdSize;
561*b7c941bbSAndroid Build Coastguard Worker         snprintf(csdName, sizeof(csdName), "csd-%d", i);
562*b7c941bbSAndroid Build Coastguard Worker         if (AMediaFormat_getBuffer(mInpDecDupFormat, csdName, &csdBuffer, &csdSize)) {
563*b7c941bbSAndroid Build Coastguard Worker             mCsdBuffers.emplace_back(std::make_pair(csdBuffer, csdSize));
564*b7c941bbSAndroid Build Coastguard Worker             AMediaFormat_setBuffer(mInpDecFormat, csdName, nullptr, 0);
565*b7c941bbSAndroid Build Coastguard Worker         } else break;
566*b7c941bbSAndroid Build Coastguard Worker     }
567*b7c941bbSAndroid Build Coastguard Worker 
568*b7c941bbSAndroid Build Coastguard Worker     const bool boolStates[]{true, false};
569*b7c941bbSAndroid Build Coastguard Worker     mSaveToMem = true;
570*b7c941bbSAndroid Build Coastguard Worker     auto ref = mRefBuff;
571*b7c941bbSAndroid Build Coastguard Worker     auto test = mTestBuff;
572*b7c941bbSAndroid Build Coastguard Worker     int loopCounter = 0;
573*b7c941bbSAndroid Build Coastguard Worker     for (int i = 0; i < formats.size(); i++) {
574*b7c941bbSAndroid Build Coastguard Worker         auto fmt = formats[i];
575*b7c941bbSAndroid Build Coastguard Worker         for (auto eosType : boolStates) {
576*b7c941bbSAndroid Build Coastguard Worker             for (auto isAsync : boolStates) {
577*b7c941bbSAndroid Build Coastguard Worker                 bool validateFormat = true;
578*b7c941bbSAndroid Build Coastguard Worker                 mOutputBuff = loopCounter == 0 ? ref : test;
579*b7c941bbSAndroid Build Coastguard Worker                 mOutputBuff->reset();
580*b7c941bbSAndroid Build Coastguard Worker                 /* TODO(b/149981033) */
581*b7c941bbSAndroid Build Coastguard Worker                 /* Instead of create and delete codec at every iteration, we would like to create
582*b7c941bbSAndroid Build Coastguard Worker                  * once and use it for all iterations and delete before exiting */
583*b7c941bbSAndroid Build Coastguard Worker                 mCodec = AMediaCodec_createCodecByName(decoder);
584*b7c941bbSAndroid Build Coastguard Worker                 RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
585*b7c941bbSAndroid Build Coastguard Worker                 AMediaExtractor_seekTo(mExtractor, 0, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
586*b7c941bbSAndroid Build Coastguard Worker                 if (!configureCodec(fmt, isAsync, eosType, false)) return false;
587*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat* defFormat = AMediaCodec_getOutputFormat(mCodec);
588*b7c941bbSAndroid Build Coastguard Worker                 if (isFormatSimilar(defFormat, mInpDecFormat)) {
589*b7c941bbSAndroid Build Coastguard Worker                     ALOGD("Input format is same as default for format for %s", decoder);
590*b7c941bbSAndroid Build Coastguard Worker                     validateFormat = false;
591*b7c941bbSAndroid Build Coastguard Worker                 }
592*b7c941bbSAndroid Build Coastguard Worker                 AMediaFormat_delete(defFormat);
593*b7c941bbSAndroid Build Coastguard Worker                 RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
594*b7c941bbSAndroid Build Coastguard Worker                 /* formats[0] doesn't contain csd-data, so queuing csd separately, formats[1]
595*b7c941bbSAndroid Build Coastguard Worker                  * contain csd-data */
596*b7c941bbSAndroid Build Coastguard Worker                 if (i == 0 && !queueCodecConfig()) return false;
597*b7c941bbSAndroid Build Coastguard Worker                 if (!doWork(INT32_MAX)) return false;
598*b7c941bbSAndroid Build Coastguard Worker                 if (!queueEOS()) return false;
599*b7c941bbSAndroid Build Coastguard Worker                 if (!waitForAllOutputs()) return false;
600*b7c941bbSAndroid Build Coastguard Worker                 RETURN_IF_FAIL(AMediaCodec_stop(mCodec), "AMediaCodec_stop failed")
601*b7c941bbSAndroid Build Coastguard Worker                 RETURN_IF_FAIL(AMediaCodec_delete(mCodec), "AMediaCodec_delete failed")
602*b7c941bbSAndroid Build Coastguard Worker                 mCodec = nullptr;
603*b7c941bbSAndroid Build Coastguard Worker                 RETURN_IF_TRUE((loopCounter != 0 && !ref->equals(test)),
604*b7c941bbSAndroid Build Coastguard Worker                                std::string{"Decoder output is not consistent across runs \n"}
605*b7c941bbSAndroid Build Coastguard Worker                                        .append(test->getErrorMsg()))
606*b7c941bbSAndroid Build Coastguard Worker                 if (validateFormat && !isOutputFormatOk(mInpDecFormat)) {
607*b7c941bbSAndroid Build Coastguard Worker                     return false;
608*b7c941bbSAndroid Build Coastguard Worker                 }
609*b7c941bbSAndroid Build Coastguard Worker                 loopCounter++;
610*b7c941bbSAndroid Build Coastguard Worker             }
611*b7c941bbSAndroid Build Coastguard Worker         }
612*b7c941bbSAndroid Build Coastguard Worker     }
613*b7c941bbSAndroid Build Coastguard Worker     mSaveToMem = false;
614*b7c941bbSAndroid Build Coastguard Worker     return true;
615*b7c941bbSAndroid Build Coastguard Worker }
616*b7c941bbSAndroid Build Coastguard Worker 
nativeTestSimpleDecode(JNIEnv * env,jobject,jstring jDecoder,jobject surface,jstring jMediaType,jstring jtestFile,jstring jrefFile,jint jColorFormat,jfloat jrmsError,jlong jChecksum,jobject jRetMsg)617*b7c941bbSAndroid Build Coastguard Worker jboolean nativeTestSimpleDecode(JNIEnv* env, jobject, jstring jDecoder, jobject surface,
618*b7c941bbSAndroid Build Coastguard Worker                                 jstring jMediaType, jstring jtestFile, jstring jrefFile,
619*b7c941bbSAndroid Build Coastguard Worker                                 jint jColorFormat, jfloat jrmsError, jlong jChecksum,
620*b7c941bbSAndroid Build Coastguard Worker                                 jobject jRetMsg) {
621*b7c941bbSAndroid Build Coastguard Worker     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
622*b7c941bbSAndroid Build Coastguard Worker     const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
623*b7c941bbSAndroid Build Coastguard Worker     const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
624*b7c941bbSAndroid Build Coastguard Worker     const char* cRefFile = env->GetStringUTFChars(jrefFile, nullptr);
625*b7c941bbSAndroid Build Coastguard Worker     float cRmsError = jrmsError;
626*b7c941bbSAndroid Build Coastguard Worker     uLong cChecksum = jChecksum;
627*b7c941bbSAndroid Build Coastguard Worker     ANativeWindow* window = surface ? ANativeWindow_fromSurface(env, surface) : nullptr;
628*b7c941bbSAndroid Build Coastguard Worker     auto* codecDecoderTest = new CodecDecoderTest(cMediaType, window);
629*b7c941bbSAndroid Build Coastguard Worker     bool isPass = codecDecoderTest->testSimpleDecode(cDecoder, cTestFile, cRefFile, jColorFormat,
630*b7c941bbSAndroid Build Coastguard Worker                                                      cRmsError, cChecksum);
631*b7c941bbSAndroid Build Coastguard Worker     std::string msg = isPass ? std::string{} : codecDecoderTest->getErrorMsg();
632*b7c941bbSAndroid Build Coastguard Worker     delete codecDecoderTest;
633*b7c941bbSAndroid Build Coastguard Worker     jclass clazz = env->GetObjectClass(jRetMsg);
634*b7c941bbSAndroid Build Coastguard Worker     jmethodID mId =
635*b7c941bbSAndroid Build Coastguard Worker             env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
636*b7c941bbSAndroid Build Coastguard Worker     env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
637*b7c941bbSAndroid Build Coastguard Worker     if (window) {
638*b7c941bbSAndroid Build Coastguard Worker         ANativeWindow_release(window);
639*b7c941bbSAndroid Build Coastguard Worker         window = nullptr;
640*b7c941bbSAndroid Build Coastguard Worker     }
641*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jDecoder, cDecoder);
642*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jMediaType, cMediaType);
643*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jtestFile, cTestFile);
644*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jrefFile, cRefFile);
645*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
646*b7c941bbSAndroid Build Coastguard Worker }
647*b7c941bbSAndroid Build Coastguard Worker 
nativeTestOnlyEos(JNIEnv * env,jobject,jstring jDecoder,jstring jMediaType,jstring jtestFile,jint jColorFormat,jobject jRetMsg)648*b7c941bbSAndroid Build Coastguard Worker jboolean nativeTestOnlyEos(JNIEnv* env, jobject, jstring jDecoder, jstring jMediaType,
649*b7c941bbSAndroid Build Coastguard Worker                            jstring jtestFile, jint jColorFormat, jobject jRetMsg) {
650*b7c941bbSAndroid Build Coastguard Worker     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
651*b7c941bbSAndroid Build Coastguard Worker     const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
652*b7c941bbSAndroid Build Coastguard Worker     const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
653*b7c941bbSAndroid Build Coastguard Worker     auto* codecDecoderTest = new CodecDecoderTest(cMediaType, nullptr);
654*b7c941bbSAndroid Build Coastguard Worker     bool isPass = codecDecoderTest->testOnlyEos(cDecoder, cTestFile, jColorFormat);
655*b7c941bbSAndroid Build Coastguard Worker     std::string msg = isPass ? std::string{} : codecDecoderTest->getErrorMsg();
656*b7c941bbSAndroid Build Coastguard Worker     delete codecDecoderTest;
657*b7c941bbSAndroid Build Coastguard Worker     jclass clazz = env->GetObjectClass(jRetMsg);
658*b7c941bbSAndroid Build Coastguard Worker     jmethodID mId =
659*b7c941bbSAndroid Build Coastguard Worker             env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
660*b7c941bbSAndroid Build Coastguard Worker     env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
661*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jDecoder, cDecoder);
662*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jMediaType, cMediaType);
663*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jtestFile, cTestFile);
664*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
665*b7c941bbSAndroid Build Coastguard Worker }
666*b7c941bbSAndroid Build Coastguard Worker 
nativeTestFlush(JNIEnv * env,jobject,jstring jDecoder,jobject surface,jstring jMediaType,jstring jtestFile,jint jColorFormat,jobject jRetMsg)667*b7c941bbSAndroid Build Coastguard Worker jboolean nativeTestFlush(JNIEnv* env, jobject, jstring jDecoder, jobject surface,
668*b7c941bbSAndroid Build Coastguard Worker                          jstring jMediaType, jstring jtestFile, jint jColorFormat,
669*b7c941bbSAndroid Build Coastguard Worker                          jobject jRetMsg) {
670*b7c941bbSAndroid Build Coastguard Worker     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
671*b7c941bbSAndroid Build Coastguard Worker     const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
672*b7c941bbSAndroid Build Coastguard Worker     const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
673*b7c941bbSAndroid Build Coastguard Worker     ANativeWindow* window = surface ? ANativeWindow_fromSurface(env, surface) : nullptr;
674*b7c941bbSAndroid Build Coastguard Worker     auto* codecDecoderTest = new CodecDecoderTest(cMediaType, window);
675*b7c941bbSAndroid Build Coastguard Worker     bool isPass = codecDecoderTest->testFlush(cDecoder, cTestFile, jColorFormat);
676*b7c941bbSAndroid Build Coastguard Worker     std::string msg = isPass ? std::string{} : codecDecoderTest->getErrorMsg();
677*b7c941bbSAndroid Build Coastguard Worker     delete codecDecoderTest;
678*b7c941bbSAndroid Build Coastguard Worker     jclass clazz = env->GetObjectClass(jRetMsg);
679*b7c941bbSAndroid Build Coastguard Worker     jmethodID mId =
680*b7c941bbSAndroid Build Coastguard Worker             env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
681*b7c941bbSAndroid Build Coastguard Worker     env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
682*b7c941bbSAndroid Build Coastguard Worker     if (window) {
683*b7c941bbSAndroid Build Coastguard Worker         ANativeWindow_release(window);
684*b7c941bbSAndroid Build Coastguard Worker         window = nullptr;
685*b7c941bbSAndroid Build Coastguard Worker     }
686*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jDecoder, cDecoder);
687*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jMediaType, cMediaType);
688*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jtestFile, cTestFile);
689*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
690*b7c941bbSAndroid Build Coastguard Worker }
691*b7c941bbSAndroid Build Coastguard Worker 
nativeTestSimpleDecodeQueueCSD(JNIEnv * env,jobject,jstring jDecoder,jstring jMediaType,jstring jtestFile,jint jColorFormat,jobject jRetMsg)692*b7c941bbSAndroid Build Coastguard Worker jboolean nativeTestSimpleDecodeQueueCSD(JNIEnv* env, jobject, jstring jDecoder, jstring jMediaType,
693*b7c941bbSAndroid Build Coastguard Worker                                         jstring jtestFile, jint jColorFormat, jobject jRetMsg) {
694*b7c941bbSAndroid Build Coastguard Worker     const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
695*b7c941bbSAndroid Build Coastguard Worker     const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
696*b7c941bbSAndroid Build Coastguard Worker     const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
697*b7c941bbSAndroid Build Coastguard Worker     auto codecDecoderTest = new CodecDecoderTest(cMediaType, nullptr);
698*b7c941bbSAndroid Build Coastguard Worker     bool isPass = codecDecoderTest->testSimpleDecodeQueueCSD(cDecoder, cTestFile, jColorFormat);
699*b7c941bbSAndroid Build Coastguard Worker     std::string msg = isPass ? std::string{} : codecDecoderTest->getErrorMsg();
700*b7c941bbSAndroid Build Coastguard Worker     delete codecDecoderTest;
701*b7c941bbSAndroid Build Coastguard Worker     jclass clazz = env->GetObjectClass(jRetMsg);
702*b7c941bbSAndroid Build Coastguard Worker     jmethodID mId =
703*b7c941bbSAndroid Build Coastguard Worker             env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
704*b7c941bbSAndroid Build Coastguard Worker     env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
705*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jDecoder, cDecoder);
706*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jMediaType, cMediaType);
707*b7c941bbSAndroid Build Coastguard Worker     env->ReleaseStringUTFChars(jtestFile, cTestFile);
708*b7c941bbSAndroid Build Coastguard Worker     return static_cast<jboolean>(isPass);
709*b7c941bbSAndroid Build Coastguard Worker }
710