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