1*b7c941bbSAndroid Build Coastguard Worker /*
2*b7c941bbSAndroid Build Coastguard Worker * Copyright (C) 2019 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 "NativeExtractorTest"
19*b7c941bbSAndroid Build Coastguard Worker #include <log/log.h>
20*b7c941bbSAndroid Build Coastguard Worker
21*b7c941bbSAndroid Build Coastguard Worker #include <jni.h>
22*b7c941bbSAndroid Build Coastguard Worker #include <media/NdkMediaExtractor.h>
23*b7c941bbSAndroid Build Coastguard Worker #include <sys/stat.h>
24*b7c941bbSAndroid Build Coastguard Worker #include <zlib.h>
25*b7c941bbSAndroid Build Coastguard Worker
26*b7c941bbSAndroid Build Coastguard Worker #include <cstdlib>
27*b7c941bbSAndroid Build Coastguard Worker #include <random>
28*b7c941bbSAndroid Build Coastguard Worker
29*b7c941bbSAndroid Build Coastguard Worker #include "NativeMediaCommon.h"
30*b7c941bbSAndroid Build Coastguard Worker
31*b7c941bbSAndroid Build Coastguard Worker #define CHECK_KEY(hasKey, format, isPass) \
32*b7c941bbSAndroid Build Coastguard Worker if (!(hasKey)) { \
33*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete((format)); \
34*b7c941bbSAndroid Build Coastguard Worker (isPass) = false; \
35*b7c941bbSAndroid Build Coastguard Worker break; \
36*b7c941bbSAndroid Build Coastguard Worker }
37*b7c941bbSAndroid Build Coastguard Worker
isExtractorOKonEOS(AMediaExtractor * extractor)38*b7c941bbSAndroid Build Coastguard Worker static bool isExtractorOKonEOS(AMediaExtractor* extractor) {
39*b7c941bbSAndroid Build Coastguard Worker return AMediaExtractor_getSampleTrackIndex(extractor) < 0 &&
40*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_getSampleSize(extractor) < 0 &&
41*b7c941bbSAndroid Build Coastguard Worker (int)AMediaExtractor_getSampleFlags(extractor) < 0 &&
42*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_getSampleTime(extractor) < 0;
43*b7c941bbSAndroid Build Coastguard Worker }
44*b7c941bbSAndroid Build Coastguard Worker
isSampleInfoIdentical(AMediaCodecBufferInfo * refSample,AMediaCodecBufferInfo * testSample)45*b7c941bbSAndroid Build Coastguard Worker static bool isSampleInfoIdentical(AMediaCodecBufferInfo* refSample,
46*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo* testSample) {
47*b7c941bbSAndroid Build Coastguard Worker return refSample->flags == testSample->flags && refSample->size == testSample->size &&
48*b7c941bbSAndroid Build Coastguard Worker refSample->presentationTimeUs == testSample->presentationTimeUs;
49*b7c941bbSAndroid Build Coastguard Worker }
50*b7c941bbSAndroid Build Coastguard Worker
isSampleInfoValidAndIdentical(AMediaCodecBufferInfo * refSample,AMediaCodecBufferInfo * testSample)51*b7c941bbSAndroid Build Coastguard Worker static bool isSampleInfoValidAndIdentical(AMediaCodecBufferInfo* refSample,
52*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo* testSample) {
53*b7c941bbSAndroid Build Coastguard Worker return refSample->flags == testSample->flags && refSample->size == testSample->size &&
54*b7c941bbSAndroid Build Coastguard Worker abs(refSample->presentationTimeUs - testSample->presentationTimeUs) <= 1 &&
55*b7c941bbSAndroid Build Coastguard Worker (int)refSample->flags >= 0 && refSample->size >= 0 && refSample->presentationTimeUs >= 0;
56*b7c941bbSAndroid Build Coastguard Worker }
57*b7c941bbSAndroid Build Coastguard Worker
setSampleInfo(AMediaExtractor * extractor,AMediaCodecBufferInfo * info)58*b7c941bbSAndroid Build Coastguard Worker static void inline setSampleInfo(AMediaExtractor* extractor, AMediaCodecBufferInfo* info) {
59*b7c941bbSAndroid Build Coastguard Worker info->flags = AMediaExtractor_getSampleFlags(extractor);
60*b7c941bbSAndroid Build Coastguard Worker info->offset = 0;
61*b7c941bbSAndroid Build Coastguard Worker info->size = AMediaExtractor_getSampleSize(extractor);
62*b7c941bbSAndroid Build Coastguard Worker info->presentationTimeUs = AMediaExtractor_getSampleTime(extractor);
63*b7c941bbSAndroid Build Coastguard Worker }
64*b7c941bbSAndroid Build Coastguard Worker
isMediaSimilar(AMediaExtractor * refExtractor,AMediaExtractor * testExtractor,const char * mediaType,int sampleLimit=INT32_MAX)65*b7c941bbSAndroid Build Coastguard Worker static bool isMediaSimilar(AMediaExtractor* refExtractor, AMediaExtractor* testExtractor,
66*b7c941bbSAndroid Build Coastguard Worker const char* mediaType, int sampleLimit = INT32_MAX) {
67*b7c941bbSAndroid Build Coastguard Worker const int maxSampleSize = (4 * 1024 * 1024);
68*b7c941bbSAndroid Build Coastguard Worker auto refBuffer = new uint8_t[maxSampleSize];
69*b7c941bbSAndroid Build Coastguard Worker auto testBuffer = new uint8_t[maxSampleSize];
70*b7c941bbSAndroid Build Coastguard Worker int noOfTracksMatched = 0;
71*b7c941bbSAndroid Build Coastguard Worker for (size_t refTrackID = 0; refTrackID < AMediaExtractor_getTrackCount(refExtractor);
72*b7c941bbSAndroid Build Coastguard Worker refTrackID++) {
73*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* refFormat = AMediaExtractor_getTrackFormat(refExtractor, refTrackID);
74*b7c941bbSAndroid Build Coastguard Worker const char* refMediaType = nullptr;
75*b7c941bbSAndroid Build Coastguard Worker bool hasKey = AMediaFormat_getString(refFormat, AMEDIAFORMAT_KEY_MIME, &refMediaType);
76*b7c941bbSAndroid Build Coastguard Worker if (!hasKey || (mediaType != nullptr && strcmp(refMediaType, mediaType) != 0)) {
77*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(refFormat);
78*b7c941bbSAndroid Build Coastguard Worker continue;
79*b7c941bbSAndroid Build Coastguard Worker }
80*b7c941bbSAndroid Build Coastguard Worker for (size_t testTrackID = 0; testTrackID < AMediaExtractor_getTrackCount(testExtractor);
81*b7c941bbSAndroid Build Coastguard Worker testTrackID++) {
82*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* testFormat = AMediaExtractor_getTrackFormat(testExtractor, testTrackID);
83*b7c941bbSAndroid Build Coastguard Worker if (!isFormatSimilar(refFormat, testFormat)) {
84*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(testFormat);
85*b7c941bbSAndroid Build Coastguard Worker continue;
86*b7c941bbSAndroid Build Coastguard Worker }
87*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(refExtractor, refTrackID);
88*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(testExtractor, testTrackID);
89*b7c941bbSAndroid Build Coastguard Worker
90*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo refSampleInfo, testSampleInfo;
91*b7c941bbSAndroid Build Coastguard Worker bool areTracksIdentical = true;
92*b7c941bbSAndroid Build Coastguard Worker for (int frameCount = 0;; frameCount++) {
93*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(refExtractor, &refSampleInfo);
94*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(testExtractor, &testSampleInfo);
95*b7c941bbSAndroid Build Coastguard Worker if (!isSampleInfoValidAndIdentical(&refSampleInfo, &testSampleInfo)) {
96*b7c941bbSAndroid Build Coastguard Worker ALOGD(" MediaType: %s mismatch for sample: %d", refMediaType, frameCount);
97*b7c941bbSAndroid Build Coastguard Worker ALOGD(" flags exp/got: %d / %d", refSampleInfo.flags, testSampleInfo.flags);
98*b7c941bbSAndroid Build Coastguard Worker ALOGD(" size exp/got: %d / %d ", refSampleInfo.size, testSampleInfo.size);
99*b7c941bbSAndroid Build Coastguard Worker ALOGD(" ts exp/got: %" PRId64 " / %" PRId64 "",
100*b7c941bbSAndroid Build Coastguard Worker refSampleInfo.presentationTimeUs, testSampleInfo.presentationTimeUs);
101*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
102*b7c941bbSAndroid Build Coastguard Worker break;
103*b7c941bbSAndroid Build Coastguard Worker }
104*b7c941bbSAndroid Build Coastguard Worker ssize_t refSz =
105*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_readSampleData(refExtractor, refBuffer, maxSampleSize);
106*b7c941bbSAndroid Build Coastguard Worker if (refSz != refSampleInfo.size) {
107*b7c941bbSAndroid Build Coastguard Worker ALOGD("MediaType: %s Size exp/got: %d / %zd ", mediaType, refSampleInfo.size,
108*b7c941bbSAndroid Build Coastguard Worker refSz);
109*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
110*b7c941bbSAndroid Build Coastguard Worker break;
111*b7c941bbSAndroid Build Coastguard Worker }
112*b7c941bbSAndroid Build Coastguard Worker ssize_t testSz =
113*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_readSampleData(testExtractor, testBuffer, maxSampleSize);
114*b7c941bbSAndroid Build Coastguard Worker if (testSz != testSampleInfo.size) {
115*b7c941bbSAndroid Build Coastguard Worker ALOGD("MediaType: %s Size exp/got: %d / %zd ", mediaType, testSampleInfo.size,
116*b7c941bbSAndroid Build Coastguard Worker testSz);
117*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
118*b7c941bbSAndroid Build Coastguard Worker break;
119*b7c941bbSAndroid Build Coastguard Worker }
120*b7c941bbSAndroid Build Coastguard Worker int trackIndex = AMediaExtractor_getSampleTrackIndex(refExtractor);
121*b7c941bbSAndroid Build Coastguard Worker if (trackIndex != refTrackID) {
122*b7c941bbSAndroid Build Coastguard Worker ALOGD("MediaType: %s TrackID exp/got: %zu / %d", mediaType, refTrackID,
123*b7c941bbSAndroid Build Coastguard Worker trackIndex);
124*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
125*b7c941bbSAndroid Build Coastguard Worker break;
126*b7c941bbSAndroid Build Coastguard Worker }
127*b7c941bbSAndroid Build Coastguard Worker trackIndex = AMediaExtractor_getSampleTrackIndex(testExtractor);
128*b7c941bbSAndroid Build Coastguard Worker if (trackIndex != testTrackID) {
129*b7c941bbSAndroid Build Coastguard Worker ALOGD("MediaType: %s TrackID exp/got %zd / %d : ", mediaType, testTrackID,
130*b7c941bbSAndroid Build Coastguard Worker trackIndex);
131*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
132*b7c941bbSAndroid Build Coastguard Worker break;
133*b7c941bbSAndroid Build Coastguard Worker }
134*b7c941bbSAndroid Build Coastguard Worker if (memcmp(refBuffer, testBuffer, refSz)) {
135*b7c941bbSAndroid Build Coastguard Worker ALOGD("MediaType: %s Mismatch in sample data", mediaType);
136*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
137*b7c941bbSAndroid Build Coastguard Worker break;
138*b7c941bbSAndroid Build Coastguard Worker }
139*b7c941bbSAndroid Build Coastguard Worker bool haveRefSamples = AMediaExtractor_advance(refExtractor);
140*b7c941bbSAndroid Build Coastguard Worker bool haveTestSamples = AMediaExtractor_advance(testExtractor);
141*b7c941bbSAndroid Build Coastguard Worker if (haveRefSamples != haveTestSamples) {
142*b7c941bbSAndroid Build Coastguard Worker ALOGD("MediaType: %s Mismatch in sampleCount", mediaType);
143*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
144*b7c941bbSAndroid Build Coastguard Worker break;
145*b7c941bbSAndroid Build Coastguard Worker }
146*b7c941bbSAndroid Build Coastguard Worker
147*b7c941bbSAndroid Build Coastguard Worker if (!haveRefSamples && !isExtractorOKonEOS(refExtractor)) {
148*b7c941bbSAndroid Build Coastguard Worker ALOGD("MediaType: %s calls post advance() are not OK", mediaType);
149*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
150*b7c941bbSAndroid Build Coastguard Worker break;
151*b7c941bbSAndroid Build Coastguard Worker }
152*b7c941bbSAndroid Build Coastguard Worker if (!haveTestSamples && !isExtractorOKonEOS(testExtractor)) {
153*b7c941bbSAndroid Build Coastguard Worker ALOGD("MediaType: %s calls post advance() are not OK", mediaType);
154*b7c941bbSAndroid Build Coastguard Worker areTracksIdentical = false;
155*b7c941bbSAndroid Build Coastguard Worker break;
156*b7c941bbSAndroid Build Coastguard Worker }
157*b7c941bbSAndroid Build Coastguard Worker ALOGV("MediaType: %s Sample: %d flags: %d size: %d ts: % " PRId64 "", mediaType,
158*b7c941bbSAndroid Build Coastguard Worker frameCount, refSampleInfo.flags, refSampleInfo.size,
159*b7c941bbSAndroid Build Coastguard Worker refSampleInfo.presentationTimeUs);
160*b7c941bbSAndroid Build Coastguard Worker if (!haveRefSamples || frameCount >= sampleLimit) {
161*b7c941bbSAndroid Build Coastguard Worker break;
162*b7c941bbSAndroid Build Coastguard Worker }
163*b7c941bbSAndroid Build Coastguard Worker }
164*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(testExtractor, testTrackID);
165*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(refExtractor, refTrackID);
166*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(testFormat);
167*b7c941bbSAndroid Build Coastguard Worker if (areTracksIdentical) {
168*b7c941bbSAndroid Build Coastguard Worker noOfTracksMatched++;
169*b7c941bbSAndroid Build Coastguard Worker break;
170*b7c941bbSAndroid Build Coastguard Worker }
171*b7c941bbSAndroid Build Coastguard Worker }
172*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(refFormat);
173*b7c941bbSAndroid Build Coastguard Worker if (mediaType != nullptr && noOfTracksMatched > 0) break;
174*b7c941bbSAndroid Build Coastguard Worker }
175*b7c941bbSAndroid Build Coastguard Worker delete[] refBuffer;
176*b7c941bbSAndroid Build Coastguard Worker delete[] testBuffer;
177*b7c941bbSAndroid Build Coastguard Worker if (mediaType == nullptr) {
178*b7c941bbSAndroid Build Coastguard Worker return noOfTracksMatched == AMediaExtractor_getTrackCount(refExtractor);
179*b7c941bbSAndroid Build Coastguard Worker } else {
180*b7c941bbSAndroid Build Coastguard Worker return noOfTracksMatched > 0;
181*b7c941bbSAndroid Build Coastguard Worker }
182*b7c941bbSAndroid Build Coastguard Worker }
183*b7c941bbSAndroid Build Coastguard Worker
validateCachedDuration(AMediaExtractor * extractor,bool isNetworkSource)184*b7c941bbSAndroid Build Coastguard Worker static bool validateCachedDuration(AMediaExtractor* extractor, bool isNetworkSource) {
185*b7c941bbSAndroid Build Coastguard Worker if (isNetworkSource) {
186*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(extractor, 0);
187*b7c941bbSAndroid Build Coastguard Worker for (unsigned cnt = 0;; cnt++) {
188*b7c941bbSAndroid Build Coastguard Worker if ((cnt & (cnt - 1)) == 0) {
189*b7c941bbSAndroid Build Coastguard Worker if (AMediaExtractor_getCachedDuration(extractor) < 0) {
190*b7c941bbSAndroid Build Coastguard Worker ALOGE("getCachedDuration is less than zero for network source");
191*b7c941bbSAndroid Build Coastguard Worker return false;
192*b7c941bbSAndroid Build Coastguard Worker }
193*b7c941bbSAndroid Build Coastguard Worker }
194*b7c941bbSAndroid Build Coastguard Worker if (!AMediaExtractor_advance(extractor)) break;
195*b7c941bbSAndroid Build Coastguard Worker }
196*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(extractor, 0);
197*b7c941bbSAndroid Build Coastguard Worker } else {
198*b7c941bbSAndroid Build Coastguard Worker if (AMediaExtractor_getCachedDuration(extractor) != -1) {
199*b7c941bbSAndroid Build Coastguard Worker ALOGE("getCachedDuration != -1 for non-network source");
200*b7c941bbSAndroid Build Coastguard Worker return false;
201*b7c941bbSAndroid Build Coastguard Worker }
202*b7c941bbSAndroid Build Coastguard Worker }
203*b7c941bbSAndroid Build Coastguard Worker return true;
204*b7c941bbSAndroid Build Coastguard Worker }
205*b7c941bbSAndroid Build Coastguard Worker
createExtractorFromFD(FILE * fp)206*b7c941bbSAndroid Build Coastguard Worker static AMediaExtractor* createExtractorFromFD(FILE* fp) {
207*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* extractor = nullptr;
208*b7c941bbSAndroid Build Coastguard Worker struct stat buf {};
209*b7c941bbSAndroid Build Coastguard Worker if (fp && !fstat(fileno(fp), &buf)) {
210*b7c941bbSAndroid Build Coastguard Worker extractor = AMediaExtractor_new();
211*b7c941bbSAndroid Build Coastguard Worker media_status_t res = AMediaExtractor_setDataSourceFd(extractor, fileno(fp), 0, buf.st_size);
212*b7c941bbSAndroid Build Coastguard Worker if (res != AMEDIA_OK) {
213*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_delete(extractor);
214*b7c941bbSAndroid Build Coastguard Worker extractor = nullptr;
215*b7c941bbSAndroid Build Coastguard Worker }
216*b7c941bbSAndroid Build Coastguard Worker }
217*b7c941bbSAndroid Build Coastguard Worker return extractor;
218*b7c941bbSAndroid Build Coastguard Worker }
219*b7c941bbSAndroid Build Coastguard Worker
createExtractorFromUrl(JNIEnv * env,jobjectArray jkeys,jobjectArray jvalues,AMediaExtractor ** ex,AMediaDataSource ** ds,const char * url)220*b7c941bbSAndroid Build Coastguard Worker static bool createExtractorFromUrl(JNIEnv* env, jobjectArray jkeys, jobjectArray jvalues,
221*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor** ex, AMediaDataSource** ds, const char* url) {
222*b7c941bbSAndroid Build Coastguard Worker int numkeys = jkeys ? env->GetArrayLength(jkeys) : 0;
223*b7c941bbSAndroid Build Coastguard Worker int numvalues = jvalues ? env->GetArrayLength(jvalues) : 0;
224*b7c941bbSAndroid Build Coastguard Worker if (numkeys != numvalues) {
225*b7c941bbSAndroid Build Coastguard Worker ALOGE("Unequal number of keys and values");
226*b7c941bbSAndroid Build Coastguard Worker return false;
227*b7c941bbSAndroid Build Coastguard Worker }
228*b7c941bbSAndroid Build Coastguard Worker const char** keyvalues = numkeys ? new const char*[numkeys * 2] : nullptr;
229*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < numkeys; i++) {
230*b7c941bbSAndroid Build Coastguard Worker auto jkey = (jstring)(env->GetObjectArrayElement(jkeys, i));
231*b7c941bbSAndroid Build Coastguard Worker auto jvalue = (jstring)(env->GetObjectArrayElement(jvalues, i));
232*b7c941bbSAndroid Build Coastguard Worker const char* key = env->GetStringUTFChars(jkey, nullptr);
233*b7c941bbSAndroid Build Coastguard Worker const char* value = env->GetStringUTFChars(jvalue, nullptr);
234*b7c941bbSAndroid Build Coastguard Worker keyvalues[i * 2] = key;
235*b7c941bbSAndroid Build Coastguard Worker keyvalues[i * 2 + 1] = value;
236*b7c941bbSAndroid Build Coastguard Worker }
237*b7c941bbSAndroid Build Coastguard Worker *ex = AMediaExtractor_new();
238*b7c941bbSAndroid Build Coastguard Worker *ds = AMediaDataSource_newUri(url, numkeys, keyvalues);
239*b7c941bbSAndroid Build Coastguard Worker bool isPass = *ds ? (AMEDIA_OK == AMediaExtractor_setDataSourceCustom(*ex, *ds)) : false;
240*b7c941bbSAndroid Build Coastguard Worker if (!isPass) ALOGE("setDataSourceCustom failed");
241*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < numkeys; i++) {
242*b7c941bbSAndroid Build Coastguard Worker auto jkey = (jstring)(env->GetObjectArrayElement(jkeys, i));
243*b7c941bbSAndroid Build Coastguard Worker auto jvalue = (jstring)(env->GetObjectArrayElement(jvalues, i));
244*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jkey, keyvalues[i * 2]);
245*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jvalue, keyvalues[i * 2 + 1]);
246*b7c941bbSAndroid Build Coastguard Worker }
247*b7c941bbSAndroid Build Coastguard Worker delete[] keyvalues;
248*b7c941bbSAndroid Build Coastguard Worker return isPass;
249*b7c941bbSAndroid Build Coastguard Worker }
250*b7c941bbSAndroid Build Coastguard Worker
251*b7c941bbSAndroid Build Coastguard Worker // content necessary for testing seek are grouped in this class
252*b7c941bbSAndroid Build Coastguard Worker class SeekTestParams {
253*b7c941bbSAndroid Build Coastguard Worker public:
SeekTestParams(AMediaCodecBufferInfo expected,int64_t timeStamp,SeekMode mode)254*b7c941bbSAndroid Build Coastguard Worker SeekTestParams(AMediaCodecBufferInfo expected, int64_t timeStamp, SeekMode mode)
255*b7c941bbSAndroid Build Coastguard Worker : mExpected{expected}, mTimeStamp{timeStamp}, mMode{mode} {}
256*b7c941bbSAndroid Build Coastguard Worker
257*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo mExpected;
258*b7c941bbSAndroid Build Coastguard Worker int64_t mTimeStamp;
259*b7c941bbSAndroid Build Coastguard Worker SeekMode mMode;
260*b7c941bbSAndroid Build Coastguard Worker };
261*b7c941bbSAndroid Build Coastguard Worker
getSeekablePoints(const char * srcFile,const char * mediaType)262*b7c941bbSAndroid Build Coastguard Worker static std::vector<AMediaCodecBufferInfo*> getSeekablePoints(const char* srcFile,
263*b7c941bbSAndroid Build Coastguard Worker const char* mediaType) {
264*b7c941bbSAndroid Build Coastguard Worker std::vector<AMediaCodecBufferInfo*> bookmarks;
265*b7c941bbSAndroid Build Coastguard Worker if (mediaType == nullptr) return bookmarks;
266*b7c941bbSAndroid Build Coastguard Worker FILE* srcFp = fopen(srcFile, "rbe");
267*b7c941bbSAndroid Build Coastguard Worker if (!srcFp) {
268*b7c941bbSAndroid Build Coastguard Worker ALOGE("fopen failed for srcFile %s", srcFile);
269*b7c941bbSAndroid Build Coastguard Worker return bookmarks;
270*b7c941bbSAndroid Build Coastguard Worker }
271*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* extractor = createExtractorFromFD(srcFp);
272*b7c941bbSAndroid Build Coastguard Worker if (!extractor) {
273*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
274*b7c941bbSAndroid Build Coastguard Worker ALOGE("createExtractorFromFD failed");
275*b7c941bbSAndroid Build Coastguard Worker return bookmarks;
276*b7c941bbSAndroid Build Coastguard Worker }
277*b7c941bbSAndroid Build Coastguard Worker
278*b7c941bbSAndroid Build Coastguard Worker for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(extractor); trackID++) {
279*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* format = AMediaExtractor_getTrackFormat(extractor, trackID);
280*b7c941bbSAndroid Build Coastguard Worker const char* currMediaType = nullptr;
281*b7c941bbSAndroid Build Coastguard Worker bool hasKey = AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &currMediaType);
282*b7c941bbSAndroid Build Coastguard Worker if (!hasKey || strcmp(currMediaType, mediaType) != 0) {
283*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
284*b7c941bbSAndroid Build Coastguard Worker continue;
285*b7c941bbSAndroid Build Coastguard Worker }
286*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(extractor, trackID);
287*b7c941bbSAndroid Build Coastguard Worker do {
288*b7c941bbSAndroid Build Coastguard Worker uint32_t sampleFlags = AMediaExtractor_getSampleFlags(extractor);
289*b7c941bbSAndroid Build Coastguard Worker if ((sampleFlags & AMEDIAEXTRACTOR_SAMPLE_FLAG_SYNC) != 0) {
290*b7c941bbSAndroid Build Coastguard Worker auto sampleInfo = new AMediaCodecBufferInfo;
291*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(extractor, sampleInfo);
292*b7c941bbSAndroid Build Coastguard Worker bookmarks.push_back(sampleInfo);
293*b7c941bbSAndroid Build Coastguard Worker }
294*b7c941bbSAndroid Build Coastguard Worker } while (AMediaExtractor_advance(extractor));
295*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(extractor, trackID);
296*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
297*b7c941bbSAndroid Build Coastguard Worker break;
298*b7c941bbSAndroid Build Coastguard Worker }
299*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_delete(extractor);
300*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
301*b7c941bbSAndroid Build Coastguard Worker return bookmarks;
302*b7c941bbSAndroid Build Coastguard Worker }
303*b7c941bbSAndroid Build Coastguard Worker
304*b7c941bbSAndroid Build Coastguard Worker static constexpr unsigned kSeed = 0x7ab7;
305*b7c941bbSAndroid Build Coastguard Worker
generateSeekTestArgs(const char * srcFile,const char * mediaType,bool isRandom)306*b7c941bbSAndroid Build Coastguard Worker static std::vector<SeekTestParams*> generateSeekTestArgs(const char* srcFile, const char* mediaType,
307*b7c941bbSAndroid Build Coastguard Worker bool isRandom) {
308*b7c941bbSAndroid Build Coastguard Worker std::vector<SeekTestParams*> testArgs;
309*b7c941bbSAndroid Build Coastguard Worker if (mediaType == nullptr) return testArgs;
310*b7c941bbSAndroid Build Coastguard Worker const int MAX_SEEK_POINTS = 7;
311*b7c941bbSAndroid Build Coastguard Worker std::srand(kSeed);
312*b7c941bbSAndroid Build Coastguard Worker if (isRandom) {
313*b7c941bbSAndroid Build Coastguard Worker FILE* srcFp = fopen(srcFile, "rbe");
314*b7c941bbSAndroid Build Coastguard Worker if (!srcFp) {
315*b7c941bbSAndroid Build Coastguard Worker ALOGE("fopen failed for srcFile %s", srcFile);
316*b7c941bbSAndroid Build Coastguard Worker return testArgs;
317*b7c941bbSAndroid Build Coastguard Worker }
318*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* extractor = createExtractorFromFD(srcFp);
319*b7c941bbSAndroid Build Coastguard Worker if (!extractor) {
320*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
321*b7c941bbSAndroid Build Coastguard Worker ALOGE("createExtractorFromFD failed");
322*b7c941bbSAndroid Build Coastguard Worker return testArgs;
323*b7c941bbSAndroid Build Coastguard Worker }
324*b7c941bbSAndroid Build Coastguard Worker
325*b7c941bbSAndroid Build Coastguard Worker const int64_t maxEstDuration = 4000000;
326*b7c941bbSAndroid Build Coastguard Worker for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(extractor); trackID++) {
327*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* format = AMediaExtractor_getTrackFormat(extractor, trackID);
328*b7c941bbSAndroid Build Coastguard Worker const char* currMediaType = nullptr;
329*b7c941bbSAndroid Build Coastguard Worker bool hasKey = AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &currMediaType);
330*b7c941bbSAndroid Build Coastguard Worker if (!hasKey || strcmp(currMediaType, mediaType) != 0) {
331*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
332*b7c941bbSAndroid Build Coastguard Worker continue;
333*b7c941bbSAndroid Build Coastguard Worker }
334*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(extractor, trackID);
335*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < MAX_SEEK_POINTS; i++) {
336*b7c941bbSAndroid Build Coastguard Worker double r = ((double)rand() / (RAND_MAX));
337*b7c941bbSAndroid Build Coastguard Worker long pts = (long)(r * maxEstDuration);
338*b7c941bbSAndroid Build Coastguard Worker
339*b7c941bbSAndroid Build Coastguard Worker for (int mode = AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC;
340*b7c941bbSAndroid Build Coastguard Worker mode <= AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC; mode++) {
341*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_seekTo(extractor, pts, (SeekMode)mode);
342*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo currInfo;
343*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(extractor, &currInfo);
344*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back((new SeekTestParams(currInfo, pts, (SeekMode)mode)));
345*b7c941bbSAndroid Build Coastguard Worker }
346*b7c941bbSAndroid Build Coastguard Worker }
347*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(extractor, trackID);
348*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
349*b7c941bbSAndroid Build Coastguard Worker break;
350*b7c941bbSAndroid Build Coastguard Worker }
351*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_delete(extractor);
352*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
353*b7c941bbSAndroid Build Coastguard Worker } else {
354*b7c941bbSAndroid Build Coastguard Worker std::vector<AMediaCodecBufferInfo*> bookmarks = getSeekablePoints(srcFile, mediaType);
355*b7c941bbSAndroid Build Coastguard Worker if (bookmarks.empty()) return testArgs;
356*b7c941bbSAndroid Build Coastguard Worker int size = bookmarks.size();
357*b7c941bbSAndroid Build Coastguard Worker int* indices;
358*b7c941bbSAndroid Build Coastguard Worker int indexSize = 0;
359*b7c941bbSAndroid Build Coastguard Worker if (size > MAX_SEEK_POINTS) {
360*b7c941bbSAndroid Build Coastguard Worker indices = new int[MAX_SEEK_POINTS];
361*b7c941bbSAndroid Build Coastguard Worker indexSize = MAX_SEEK_POINTS;
362*b7c941bbSAndroid Build Coastguard Worker indices[0] = 0;
363*b7c941bbSAndroid Build Coastguard Worker indices[MAX_SEEK_POINTS - 1] = size - 1;
364*b7c941bbSAndroid Build Coastguard Worker for (int i = 1; i < MAX_SEEK_POINTS - 1; i++) {
365*b7c941bbSAndroid Build Coastguard Worker double r = ((double)rand() / (RAND_MAX));
366*b7c941bbSAndroid Build Coastguard Worker indices[i] = (int)(r * (MAX_SEEK_POINTS - 1) + 1);
367*b7c941bbSAndroid Build Coastguard Worker }
368*b7c941bbSAndroid Build Coastguard Worker } else {
369*b7c941bbSAndroid Build Coastguard Worker indices = new int[size];
370*b7c941bbSAndroid Build Coastguard Worker indexSize = size;
371*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < size; i++) indices[i] = i;
372*b7c941bbSAndroid Build Coastguard Worker }
373*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < indexSize; i++) {
374*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo currInfo = *bookmarks[i];
375*b7c941bbSAndroid Build Coastguard Worker int64_t pts = currInfo.presentationTimeUs;
376*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back(
377*b7c941bbSAndroid Build Coastguard Worker (new SeekTestParams(currInfo, pts, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC)));
378*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back((new SeekTestParams(currInfo, pts, AMEDIAEXTRACTOR_SEEK_NEXT_SYNC)));
379*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back(
380*b7c941bbSAndroid Build Coastguard Worker (new SeekTestParams(currInfo, pts, AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC)));
381*b7c941bbSAndroid Build Coastguard Worker if (i > 0) {
382*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo prevInfo = *bookmarks[i - 1];
383*b7c941bbSAndroid Build Coastguard Worker int64_t ptsMinus = prevInfo.presentationTimeUs;
384*b7c941bbSAndroid Build Coastguard Worker ptsMinus = pts - ((pts - ptsMinus) >> 3);
385*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back((
386*b7c941bbSAndroid Build Coastguard Worker new SeekTestParams(currInfo, ptsMinus, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC)));
387*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back(
388*b7c941bbSAndroid Build Coastguard Worker (new SeekTestParams(currInfo, ptsMinus, AMEDIAEXTRACTOR_SEEK_NEXT_SYNC)));
389*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back((new SeekTestParams(prevInfo, ptsMinus,
390*b7c941bbSAndroid Build Coastguard Worker AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC)));
391*b7c941bbSAndroid Build Coastguard Worker }
392*b7c941bbSAndroid Build Coastguard Worker if (i < size - 1) {
393*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo nextInfo = *bookmarks[i + 1];
394*b7c941bbSAndroid Build Coastguard Worker int64_t ptsPlus = nextInfo.presentationTimeUs;
395*b7c941bbSAndroid Build Coastguard Worker ptsPlus = pts + ((ptsPlus - pts) >> 3);
396*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back(
397*b7c941bbSAndroid Build Coastguard Worker (new SeekTestParams(currInfo, ptsPlus, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC)));
398*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back(
399*b7c941bbSAndroid Build Coastguard Worker (new SeekTestParams(nextInfo, ptsPlus, AMEDIAEXTRACTOR_SEEK_NEXT_SYNC)));
400*b7c941bbSAndroid Build Coastguard Worker testArgs.push_back((
401*b7c941bbSAndroid Build Coastguard Worker new SeekTestParams(currInfo, ptsPlus, AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC)));
402*b7c941bbSAndroid Build Coastguard Worker }
403*b7c941bbSAndroid Build Coastguard Worker }
404*b7c941bbSAndroid Build Coastguard Worker for (auto bookmark : bookmarks) {
405*b7c941bbSAndroid Build Coastguard Worker delete bookmark;
406*b7c941bbSAndroid Build Coastguard Worker }
407*b7c941bbSAndroid Build Coastguard Worker bookmarks.clear();
408*b7c941bbSAndroid Build Coastguard Worker delete[] indices;
409*b7c941bbSAndroid Build Coastguard Worker }
410*b7c941bbSAndroid Build Coastguard Worker return testArgs;
411*b7c941bbSAndroid Build Coastguard Worker }
412*b7c941bbSAndroid Build Coastguard Worker
checkSeekPoints(const char * srcFile,const char * mediaType,const std::vector<SeekTestParams * > & seekTestArgs)413*b7c941bbSAndroid Build Coastguard Worker static int checkSeekPoints(const char* srcFile, const char* mediaType,
414*b7c941bbSAndroid Build Coastguard Worker const std::vector<SeekTestParams*>& seekTestArgs) {
415*b7c941bbSAndroid Build Coastguard Worker int errCnt = 0;
416*b7c941bbSAndroid Build Coastguard Worker FILE* srcFp = fopen(srcFile, "rbe");
417*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* extractor = createExtractorFromFD(srcFp);
418*b7c941bbSAndroid Build Coastguard Worker if (!extractor) {
419*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
420*b7c941bbSAndroid Build Coastguard Worker ALOGE("createExtractorFromFD failed");
421*b7c941bbSAndroid Build Coastguard Worker return -1;
422*b7c941bbSAndroid Build Coastguard Worker }
423*b7c941bbSAndroid Build Coastguard Worker for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(extractor); trackID++) {
424*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* format = AMediaExtractor_getTrackFormat(extractor, trackID);
425*b7c941bbSAndroid Build Coastguard Worker const char* currMediaType = nullptr;
426*b7c941bbSAndroid Build Coastguard Worker bool hasKey = AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &currMediaType);
427*b7c941bbSAndroid Build Coastguard Worker if (!hasKey || strcmp(currMediaType, mediaType) != 0) {
428*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
429*b7c941bbSAndroid Build Coastguard Worker continue;
430*b7c941bbSAndroid Build Coastguard Worker }
431*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(extractor, trackID);
432*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo received;
433*b7c941bbSAndroid Build Coastguard Worker for (auto arg : seekTestArgs) {
434*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_seekTo(extractor, arg->mTimeStamp, arg->mMode);
435*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(extractor, &received);
436*b7c941bbSAndroid Build Coastguard Worker if (!isSampleInfoIdentical(&arg->mExpected, &received)) {
437*b7c941bbSAndroid Build Coastguard Worker ALOGE(" flags exp/got: %d / %d", arg->mExpected.flags, received.flags);
438*b7c941bbSAndroid Build Coastguard Worker ALOGE(" size exp/got: %d / %d ", arg->mExpected.size, received.size);
439*b7c941bbSAndroid Build Coastguard Worker ALOGE(" ts exp/got: %" PRId64 " / %" PRId64 "", arg->mExpected.presentationTimeUs,
440*b7c941bbSAndroid Build Coastguard Worker received.presentationTimeUs);
441*b7c941bbSAndroid Build Coastguard Worker errCnt++;
442*b7c941bbSAndroid Build Coastguard Worker }
443*b7c941bbSAndroid Build Coastguard Worker }
444*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(extractor, trackID);
445*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
446*b7c941bbSAndroid Build Coastguard Worker break;
447*b7c941bbSAndroid Build Coastguard Worker }
448*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_delete(extractor);
449*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
450*b7c941bbSAndroid Build Coastguard Worker return errCnt;
451*b7c941bbSAndroid Build Coastguard Worker }
452*b7c941bbSAndroid Build Coastguard Worker
isFileFormatIdentical(AMediaExtractor * refExtractor,AMediaExtractor * testExtractor)453*b7c941bbSAndroid Build Coastguard Worker static bool isFileFormatIdentical(AMediaExtractor* refExtractor, AMediaExtractor* testExtractor) {
454*b7c941bbSAndroid Build Coastguard Worker bool result = false;
455*b7c941bbSAndroid Build Coastguard Worker if (refExtractor && testExtractor) {
456*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* refFormat = AMediaExtractor_getFileFormat(refExtractor);
457*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* testFormat = AMediaExtractor_getFileFormat(testExtractor);
458*b7c941bbSAndroid Build Coastguard Worker if (refFormat && testFormat) {
459*b7c941bbSAndroid Build Coastguard Worker const char *refMediaType = nullptr, *testMediaType = nullptr;
460*b7c941bbSAndroid Build Coastguard Worker bool hasRefKey =
461*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_getString(refFormat, AMEDIAFORMAT_KEY_MIME, &refMediaType);
462*b7c941bbSAndroid Build Coastguard Worker bool hasTestKey =
463*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_getString(testFormat, AMEDIAFORMAT_KEY_MIME, &testMediaType);
464*b7c941bbSAndroid Build Coastguard Worker /* TODO: Not Sure if we need to verify any other parameter of file format */
465*b7c941bbSAndroid Build Coastguard Worker if (hasRefKey && hasTestKey && strcmp(refMediaType, testMediaType) == 0) {
466*b7c941bbSAndroid Build Coastguard Worker result = true;
467*b7c941bbSAndroid Build Coastguard Worker } else {
468*b7c941bbSAndroid Build Coastguard Worker ALOGE("file format exp/got : %s/%s", refMediaType, testMediaType);
469*b7c941bbSAndroid Build Coastguard Worker }
470*b7c941bbSAndroid Build Coastguard Worker }
471*b7c941bbSAndroid Build Coastguard Worker if (refFormat) AMediaFormat_delete(refFormat);
472*b7c941bbSAndroid Build Coastguard Worker if (testFormat) AMediaFormat_delete(testFormat);
473*b7c941bbSAndroid Build Coastguard Worker }
474*b7c941bbSAndroid Build Coastguard Worker return result;
475*b7c941bbSAndroid Build Coastguard Worker }
476*b7c941bbSAndroid Build Coastguard Worker
isSeekOk(AMediaExtractor * refExtractor,AMediaExtractor * testExtractor)477*b7c941bbSAndroid Build Coastguard Worker static bool isSeekOk(AMediaExtractor* refExtractor, AMediaExtractor* testExtractor) {
478*b7c941bbSAndroid Build Coastguard Worker const long maxEstDuration = 14000000;
479*b7c941bbSAndroid Build Coastguard Worker const int MAX_SEEK_POINTS = 7;
480*b7c941bbSAndroid Build Coastguard Worker std::srand(kSeed);
481*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo refSampleInfo, testSampleInfo;
482*b7c941bbSAndroid Build Coastguard Worker bool result = true;
483*b7c941bbSAndroid Build Coastguard Worker for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(refExtractor); trackID++) {
484*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(refExtractor, trackID);
485*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(testExtractor, trackID);
486*b7c941bbSAndroid Build Coastguard Worker for (int i = 0; i < MAX_SEEK_POINTS && result; i++) {
487*b7c941bbSAndroid Build Coastguard Worker double r = ((double)rand() / (RAND_MAX));
488*b7c941bbSAndroid Build Coastguard Worker long pts = (long)(r * maxEstDuration);
489*b7c941bbSAndroid Build Coastguard Worker for (int mode = AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC;
490*b7c941bbSAndroid Build Coastguard Worker mode <= AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC; mode++) {
491*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_seekTo(refExtractor, pts, (SeekMode)mode);
492*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_seekTo(testExtractor, pts, (SeekMode)mode);
493*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(refExtractor, &refSampleInfo);
494*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(testExtractor, &testSampleInfo);
495*b7c941bbSAndroid Build Coastguard Worker result = isSampleInfoIdentical(&refSampleInfo, &testSampleInfo);
496*b7c941bbSAndroid Build Coastguard Worker if (!result) {
497*b7c941bbSAndroid Build Coastguard Worker ALOGE(" flags exp/got: %d / %d", refSampleInfo.flags, testSampleInfo.flags);
498*b7c941bbSAndroid Build Coastguard Worker ALOGE(" size exp/got: %d / %d ", refSampleInfo.size, testSampleInfo.size);
499*b7c941bbSAndroid Build Coastguard Worker ALOGE(" ts exp/got: %" PRId64 " / %" PRId64 "",
500*b7c941bbSAndroid Build Coastguard Worker refSampleInfo.presentationTimeUs, testSampleInfo.presentationTimeUs);
501*b7c941bbSAndroid Build Coastguard Worker }
502*b7c941bbSAndroid Build Coastguard Worker int refTrackIdx = AMediaExtractor_getSampleTrackIndex(refExtractor);
503*b7c941bbSAndroid Build Coastguard Worker int testTrackIdx = AMediaExtractor_getSampleTrackIndex(testExtractor);
504*b7c941bbSAndroid Build Coastguard Worker if (refTrackIdx != testTrackIdx) {
505*b7c941bbSAndroid Build Coastguard Worker ALOGE("trackIdx exp/got: %d/%d ", refTrackIdx, testTrackIdx);
506*b7c941bbSAndroid Build Coastguard Worker result = false;
507*b7c941bbSAndroid Build Coastguard Worker }
508*b7c941bbSAndroid Build Coastguard Worker }
509*b7c941bbSAndroid Build Coastguard Worker }
510*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(refExtractor, trackID);
511*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(testExtractor, trackID);
512*b7c941bbSAndroid Build Coastguard Worker }
513*b7c941bbSAndroid Build Coastguard Worker return result;
514*b7c941bbSAndroid Build Coastguard Worker }
515*b7c941bbSAndroid Build Coastguard Worker
nativeReadAllData(JNIEnv * env,jobject,jstring jsrcPath,jstring jMediaType,jint sampleLimit,jobjectArray jkeys,jobjectArray jvalues,jboolean isSrcUrl)516*b7c941bbSAndroid Build Coastguard Worker static jlong nativeReadAllData(JNIEnv* env, jobject, jstring jsrcPath, jstring jMediaType,
517*b7c941bbSAndroid Build Coastguard Worker jint sampleLimit, jobjectArray jkeys, jobjectArray jvalues,
518*b7c941bbSAndroid Build Coastguard Worker jboolean isSrcUrl) {
519*b7c941bbSAndroid Build Coastguard Worker const int maxSampleSize = (4 * 1024 * 1024);
520*b7c941bbSAndroid Build Coastguard Worker bool isPass = true;
521*b7c941bbSAndroid Build Coastguard Worker uLong crc32value = 0U;
522*b7c941bbSAndroid Build Coastguard Worker const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
523*b7c941bbSAndroid Build Coastguard Worker const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
524*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* extractor = nullptr;
525*b7c941bbSAndroid Build Coastguard Worker AMediaDataSource* dataSource = nullptr;
526*b7c941bbSAndroid Build Coastguard Worker FILE* srcFp = nullptr;
527*b7c941bbSAndroid Build Coastguard Worker
528*b7c941bbSAndroid Build Coastguard Worker if (isSrcUrl) {
529*b7c941bbSAndroid Build Coastguard Worker isPass = createExtractorFromUrl(env, jkeys, jvalues, &extractor, &dataSource, csrcPath);
530*b7c941bbSAndroid Build Coastguard Worker } else {
531*b7c941bbSAndroid Build Coastguard Worker srcFp = fopen(csrcPath, "rbe");
532*b7c941bbSAndroid Build Coastguard Worker extractor = createExtractorFromFD(srcFp);
533*b7c941bbSAndroid Build Coastguard Worker if (extractor == nullptr) {
534*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
535*b7c941bbSAndroid Build Coastguard Worker isPass = false;
536*b7c941bbSAndroid Build Coastguard Worker }
537*b7c941bbSAndroid Build Coastguard Worker }
538*b7c941bbSAndroid Build Coastguard Worker if (!isPass) {
539*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jMediaType, cMediaType);
540*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcPath, csrcPath);
541*b7c941bbSAndroid Build Coastguard Worker ALOGE("Error while creating extractor");
542*b7c941bbSAndroid Build Coastguard Worker if (dataSource) AMediaDataSource_delete(dataSource);
543*b7c941bbSAndroid Build Coastguard Worker if (extractor) AMediaExtractor_delete(extractor);
544*b7c941bbSAndroid Build Coastguard Worker return static_cast<jlong>(-2);
545*b7c941bbSAndroid Build Coastguard Worker }
546*b7c941bbSAndroid Build Coastguard Worker auto buffer = new uint8_t[maxSampleSize];
547*b7c941bbSAndroid Build Coastguard Worker int bufferSize = 0;
548*b7c941bbSAndroid Build Coastguard Worker int tracksSelected = 0;
549*b7c941bbSAndroid Build Coastguard Worker for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(extractor) && isPass;
550*b7c941bbSAndroid Build Coastguard Worker trackID++) {
551*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* format = AMediaExtractor_getTrackFormat(extractor, trackID);
552*b7c941bbSAndroid Build Coastguard Worker const char* refMediaType = nullptr;
553*b7c941bbSAndroid Build Coastguard Worker CHECK_KEY(AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &refMediaType), format,
554*b7c941bbSAndroid Build Coastguard Worker isPass);
555*b7c941bbSAndroid Build Coastguard Worker if (strlen(cMediaType) != 0 && strcmp(refMediaType, cMediaType) != 0) {
556*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
557*b7c941bbSAndroid Build Coastguard Worker continue;
558*b7c941bbSAndroid Build Coastguard Worker }
559*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(extractor, trackID);
560*b7c941bbSAndroid Build Coastguard Worker tracksSelected++;
561*b7c941bbSAndroid Build Coastguard Worker if (strncmp(refMediaType, "audio/", strlen("audio/")) == 0) {
562*b7c941bbSAndroid Build Coastguard Worker int32_t refSampleRate, refNumChannels;
563*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, 0);
564*b7c941bbSAndroid Build Coastguard Worker CHECK_KEY(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &refSampleRate),
565*b7c941bbSAndroid Build Coastguard Worker format, isPass);
566*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, refSampleRate);
567*b7c941bbSAndroid Build Coastguard Worker CHECK_KEY(
568*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &refNumChannels),
569*b7c941bbSAndroid Build Coastguard Worker format, isPass);
570*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, refNumChannels);
571*b7c941bbSAndroid Build Coastguard Worker } else if (strncmp(refMediaType, "video/", strlen("video/")) == 0) {
572*b7c941bbSAndroid Build Coastguard Worker int32_t refWidth, refHeight;
573*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, 1);
574*b7c941bbSAndroid Build Coastguard Worker CHECK_KEY(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &refWidth), format,
575*b7c941bbSAndroid Build Coastguard Worker isPass);
576*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, refWidth);
577*b7c941bbSAndroid Build Coastguard Worker CHECK_KEY(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &refHeight), format,
578*b7c941bbSAndroid Build Coastguard Worker isPass);
579*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, refHeight);
580*b7c941bbSAndroid Build Coastguard Worker } else {
581*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, 2);
582*b7c941bbSAndroid Build Coastguard Worker }
583*b7c941bbSAndroid Build Coastguard Worker int64_t keyDuration = 0;
584*b7c941bbSAndroid Build Coastguard Worker CHECK_KEY(AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &keyDuration), format,
585*b7c941bbSAndroid Build Coastguard Worker isPass);
586*b7c941bbSAndroid Build Coastguard Worker flattenField<int64_t>(buffer, &bufferSize, keyDuration);
587*b7c941bbSAndroid Build Coastguard Worker // csd keys
588*b7c941bbSAndroid Build Coastguard Worker for (int i = 0;; i++) {
589*b7c941bbSAndroid Build Coastguard Worker char csdName[16];
590*b7c941bbSAndroid Build Coastguard Worker void* csdBuffer;
591*b7c941bbSAndroid Build Coastguard Worker size_t csdSize;
592*b7c941bbSAndroid Build Coastguard Worker snprintf(csdName, sizeof(csdName), "csd-%d", i);
593*b7c941bbSAndroid Build Coastguard Worker if (AMediaFormat_getBuffer(format, csdName, &csdBuffer, &csdSize)) {
594*b7c941bbSAndroid Build Coastguard Worker crc32value = crc32(crc32value, static_cast<uint8_t*>(csdBuffer), csdSize);
595*b7c941bbSAndroid Build Coastguard Worker } else
596*b7c941bbSAndroid Build Coastguard Worker break;
597*b7c941bbSAndroid Build Coastguard Worker }
598*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
599*b7c941bbSAndroid Build Coastguard Worker }
600*b7c941bbSAndroid Build Coastguard Worker if (tracksSelected < 1) {
601*b7c941bbSAndroid Build Coastguard Worker isPass = false;
602*b7c941bbSAndroid Build Coastguard Worker ALOGE("No track selected");
603*b7c941bbSAndroid Build Coastguard Worker }
604*b7c941bbSAndroid Build Coastguard Worker crc32value = crc32(crc32value, buffer, bufferSize);
605*b7c941bbSAndroid Build Coastguard Worker
606*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo sampleInfo;
607*b7c941bbSAndroid Build Coastguard Worker for (int sampleCount = 0; sampleCount < sampleLimit && isPass; sampleCount++) {
608*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(extractor, &sampleInfo);
609*b7c941bbSAndroid Build Coastguard Worker ssize_t refSz = AMediaExtractor_readSampleData(extractor, buffer, maxSampleSize);
610*b7c941bbSAndroid Build Coastguard Worker crc32value = crc32(crc32value, buffer, refSz);
611*b7c941bbSAndroid Build Coastguard Worker if (sampleInfo.size != refSz) {
612*b7c941bbSAndroid Build Coastguard Worker isPass = false;
613*b7c941bbSAndroid Build Coastguard Worker ALOGE("Buffer read size %zd mismatches extractor sample size %d", refSz,
614*b7c941bbSAndroid Build Coastguard Worker sampleInfo.size);
615*b7c941bbSAndroid Build Coastguard Worker }
616*b7c941bbSAndroid Build Coastguard Worker if (sampleInfo.flags == -1) {
617*b7c941bbSAndroid Build Coastguard Worker isPass = false;
618*b7c941bbSAndroid Build Coastguard Worker ALOGE("No extractor flags");
619*b7c941bbSAndroid Build Coastguard Worker }
620*b7c941bbSAndroid Build Coastguard Worker if (sampleInfo.presentationTimeUs == -1) {
621*b7c941bbSAndroid Build Coastguard Worker isPass = false;
622*b7c941bbSAndroid Build Coastguard Worker ALOGE("Presentation times are negative");
623*b7c941bbSAndroid Build Coastguard Worker }
624*b7c941bbSAndroid Build Coastguard Worker bufferSize = 0;
625*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, sampleInfo.size);
626*b7c941bbSAndroid Build Coastguard Worker flattenField<int32_t>(buffer, &bufferSize, sampleInfo.flags);
627*b7c941bbSAndroid Build Coastguard Worker flattenField<int64_t>(buffer, &bufferSize, sampleInfo.presentationTimeUs);
628*b7c941bbSAndroid Build Coastguard Worker crc32value = crc32(crc32value, buffer, bufferSize);
629*b7c941bbSAndroid Build Coastguard Worker sampleCount++;
630*b7c941bbSAndroid Build Coastguard Worker if (!AMediaExtractor_advance(extractor)) {
631*b7c941bbSAndroid Build Coastguard Worker if (!isExtractorOKonEOS(extractor)) {
632*b7c941bbSAndroid Build Coastguard Worker isPass = false;
633*b7c941bbSAndroid Build Coastguard Worker ALOGE("Media Type: %s calls post advance() are not OK", cMediaType);
634*b7c941bbSAndroid Build Coastguard Worker }
635*b7c941bbSAndroid Build Coastguard Worker break;
636*b7c941bbSAndroid Build Coastguard Worker }
637*b7c941bbSAndroid Build Coastguard Worker }
638*b7c941bbSAndroid Build Coastguard Worker delete[] buffer;
639*b7c941bbSAndroid Build Coastguard Worker if (extractor) AMediaExtractor_delete(extractor);
640*b7c941bbSAndroid Build Coastguard Worker if (dataSource) AMediaDataSource_delete(dataSource);
641*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
642*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jMediaType, cMediaType);
643*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcPath, csrcPath);
644*b7c941bbSAndroid Build Coastguard Worker if (!isPass) {
645*b7c941bbSAndroid Build Coastguard Worker ALOGE(" Error while extracting");
646*b7c941bbSAndroid Build Coastguard Worker return static_cast<jlong>(-3);
647*b7c941bbSAndroid Build Coastguard Worker }
648*b7c941bbSAndroid Build Coastguard Worker return static_cast<jlong>(crc32value);
649*b7c941bbSAndroid Build Coastguard Worker }
650*b7c941bbSAndroid Build Coastguard Worker
nativeTestExtract(JNIEnv * env,jobject,jstring jsrcPath,jstring jrefPath,jstring jMediaType)651*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestExtract(JNIEnv* env, jobject, jstring jsrcPath, jstring jrefPath,
652*b7c941bbSAndroid Build Coastguard Worker jstring jMediaType) {
653*b7c941bbSAndroid Build Coastguard Worker bool isPass = false;
654*b7c941bbSAndroid Build Coastguard Worker const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
655*b7c941bbSAndroid Build Coastguard Worker const char* ctestPath = env->GetStringUTFChars(jrefPath, nullptr);
656*b7c941bbSAndroid Build Coastguard Worker const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
657*b7c941bbSAndroid Build Coastguard Worker FILE* srcFp = fopen(csrcPath, "rbe");
658*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* srcExtractor = createExtractorFromFD(srcFp);
659*b7c941bbSAndroid Build Coastguard Worker FILE* testFp = fopen(ctestPath, "rbe");
660*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* testExtractor = createExtractorFromFD(testFp);
661*b7c941bbSAndroid Build Coastguard Worker if (srcExtractor && testExtractor) {
662*b7c941bbSAndroid Build Coastguard Worker isPass = isMediaSimilar(srcExtractor, testExtractor, cMediaType);
663*b7c941bbSAndroid Build Coastguard Worker if (!isPass) {
664*b7c941bbSAndroid Build Coastguard Worker ALOGE(" Src and test are different from extractor perspective");
665*b7c941bbSAndroid Build Coastguard Worker }
666*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_delete(srcExtractor);
667*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_delete(testExtractor);
668*b7c941bbSAndroid Build Coastguard Worker }
669*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
670*b7c941bbSAndroid Build Coastguard Worker if (testFp) fclose(testFp);
671*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jMediaType, cMediaType);
672*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcPath, csrcPath);
673*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jrefPath, ctestPath);
674*b7c941bbSAndroid Build Coastguard Worker return static_cast<jboolean>(isPass);
675*b7c941bbSAndroid Build Coastguard Worker }
676*b7c941bbSAndroid Build Coastguard Worker
nativeTestSeek(JNIEnv * env,jobject,jstring jsrcPath,jstring jMediaType)677*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestSeek(JNIEnv* env, jobject, jstring jsrcPath, jstring jMediaType) {
678*b7c941bbSAndroid Build Coastguard Worker bool isPass = false;
679*b7c941bbSAndroid Build Coastguard Worker const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
680*b7c941bbSAndroid Build Coastguard Worker const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
681*b7c941bbSAndroid Build Coastguard Worker std::vector<SeekTestParams*> seekTestArgs = generateSeekTestArgs(csrcPath, cMediaType, false);
682*b7c941bbSAndroid Build Coastguard Worker if (!seekTestArgs.empty()) {
683*b7c941bbSAndroid Build Coastguard Worker std::shuffle(seekTestArgs.begin(), seekTestArgs.end(), std::default_random_engine(kSeed));
684*b7c941bbSAndroid Build Coastguard Worker int seekAccErrCnt = checkSeekPoints(csrcPath, cMediaType, seekTestArgs);
685*b7c941bbSAndroid Build Coastguard Worker if (seekAccErrCnt != 0) {
686*b7c941bbSAndroid Build Coastguard Worker ALOGE("For %s seek chose inaccurate Sync point in: %d / %zu", csrcPath, seekAccErrCnt,
687*b7c941bbSAndroid Build Coastguard Worker seekTestArgs.size());
688*b7c941bbSAndroid Build Coastguard Worker isPass = false;
689*b7c941bbSAndroid Build Coastguard Worker } else {
690*b7c941bbSAndroid Build Coastguard Worker isPass = true;
691*b7c941bbSAndroid Build Coastguard Worker }
692*b7c941bbSAndroid Build Coastguard Worker for (auto seekTestArg : seekTestArgs) {
693*b7c941bbSAndroid Build Coastguard Worker delete seekTestArg;
694*b7c941bbSAndroid Build Coastguard Worker }
695*b7c941bbSAndroid Build Coastguard Worker seekTestArgs.clear();
696*b7c941bbSAndroid Build Coastguard Worker } else {
697*b7c941bbSAndroid Build Coastguard Worker ALOGE("No sync samples found.");
698*b7c941bbSAndroid Build Coastguard Worker }
699*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jMediaType, cMediaType);
700*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcPath, csrcPath);
701*b7c941bbSAndroid Build Coastguard Worker return static_cast<jboolean>(isPass);
702*b7c941bbSAndroid Build Coastguard Worker }
703*b7c941bbSAndroid Build Coastguard Worker
nativeTestSeekFlakiness(JNIEnv * env,jobject,jstring jsrcPath,jstring jMediaType)704*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestSeekFlakiness(JNIEnv* env, jobject, jstring jsrcPath,
705*b7c941bbSAndroid Build Coastguard Worker jstring jMediaType) {
706*b7c941bbSAndroid Build Coastguard Worker bool isPass = false;
707*b7c941bbSAndroid Build Coastguard Worker const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
708*b7c941bbSAndroid Build Coastguard Worker const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
709*b7c941bbSAndroid Build Coastguard Worker std::vector<SeekTestParams*> seekTestArgs = generateSeekTestArgs(csrcPath, cMediaType, true);
710*b7c941bbSAndroid Build Coastguard Worker if (!seekTestArgs.empty()) {
711*b7c941bbSAndroid Build Coastguard Worker std::shuffle(seekTestArgs.begin(), seekTestArgs.end(), std::default_random_engine(kSeed));
712*b7c941bbSAndroid Build Coastguard Worker int flakyErrCnt = checkSeekPoints(csrcPath, cMediaType, seekTestArgs);
713*b7c941bbSAndroid Build Coastguard Worker if (flakyErrCnt != 0) {
714*b7c941bbSAndroid Build Coastguard Worker ALOGE("No. of Samples where seek showed flakiness is: %d", flakyErrCnt);
715*b7c941bbSAndroid Build Coastguard Worker isPass = false;
716*b7c941bbSAndroid Build Coastguard Worker } else {
717*b7c941bbSAndroid Build Coastguard Worker isPass = true;
718*b7c941bbSAndroid Build Coastguard Worker }
719*b7c941bbSAndroid Build Coastguard Worker for (auto seekTestArg : seekTestArgs) {
720*b7c941bbSAndroid Build Coastguard Worker delete seekTestArg;
721*b7c941bbSAndroid Build Coastguard Worker }
722*b7c941bbSAndroid Build Coastguard Worker seekTestArgs.clear();
723*b7c941bbSAndroid Build Coastguard Worker } else {
724*b7c941bbSAndroid Build Coastguard Worker ALOGE("No sync samples found.");
725*b7c941bbSAndroid Build Coastguard Worker }
726*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jMediaType, cMediaType);
727*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcPath, csrcPath);
728*b7c941bbSAndroid Build Coastguard Worker return static_cast<jboolean>(isPass);
729*b7c941bbSAndroid Build Coastguard Worker }
730*b7c941bbSAndroid Build Coastguard Worker
nativeTestSeekToZero(JNIEnv * env,jobject,jstring jsrcPath,jstring jMediaType)731*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestSeekToZero(JNIEnv* env, jobject, jstring jsrcPath, jstring jMediaType) {
732*b7c941bbSAndroid Build Coastguard Worker bool isPass = false;
733*b7c941bbSAndroid Build Coastguard Worker const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
734*b7c941bbSAndroid Build Coastguard Worker const char* cMediaType = env->GetStringUTFChars(jMediaType, nullptr);
735*b7c941bbSAndroid Build Coastguard Worker FILE* srcFp = fopen(csrcPath, "rbe");
736*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* extractor = createExtractorFromFD(srcFp);
737*b7c941bbSAndroid Build Coastguard Worker if (extractor) {
738*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo sampleInfoAtZero;
739*b7c941bbSAndroid Build Coastguard Worker AMediaCodecBufferInfo currInfo;
740*b7c941bbSAndroid Build Coastguard Worker static long randomPts = 1 << 20;
741*b7c941bbSAndroid Build Coastguard Worker for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(extractor); trackID++) {
742*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* format = AMediaExtractor_getTrackFormat(extractor, trackID);
743*b7c941bbSAndroid Build Coastguard Worker if (format) {
744*b7c941bbSAndroid Build Coastguard Worker const char* currMediaType = nullptr;
745*b7c941bbSAndroid Build Coastguard Worker bool hasKey = AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &currMediaType);
746*b7c941bbSAndroid Build Coastguard Worker if (!hasKey || strcmp(currMediaType, cMediaType) != 0) {
747*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
748*b7c941bbSAndroid Build Coastguard Worker continue;
749*b7c941bbSAndroid Build Coastguard Worker }
750*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_selectTrack(extractor, trackID);
751*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(extractor, &sampleInfoAtZero);
752*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_seekTo(extractor, randomPts, AMEDIAEXTRACTOR_SEEK_NEXT_SYNC);
753*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_seekTo(extractor, 0, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
754*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(extractor, &currInfo);
755*b7c941bbSAndroid Build Coastguard Worker isPass = isSampleInfoIdentical(&sampleInfoAtZero, &currInfo);
756*b7c941bbSAndroid Build Coastguard Worker if (!isPass) {
757*b7c941bbSAndroid Build Coastguard Worker ALOGE("seen mismatch seekTo(0, SEEK_TO_CLOSEST_SYNC)");
758*b7c941bbSAndroid Build Coastguard Worker ALOGE(" flags exp/got: %d / %d", sampleInfoAtZero.flags, currInfo.flags);
759*b7c941bbSAndroid Build Coastguard Worker ALOGE(" size exp/got: %d / %d ", sampleInfoAtZero.size, currInfo.size);
760*b7c941bbSAndroid Build Coastguard Worker ALOGE(" ts exp/got: %" PRId64 " / %" PRId64 " ",
761*b7c941bbSAndroid Build Coastguard Worker sampleInfoAtZero.presentationTimeUs, currInfo.presentationTimeUs);
762*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
763*b7c941bbSAndroid Build Coastguard Worker break;
764*b7c941bbSAndroid Build Coastguard Worker }
765*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_seekTo(extractor, -1L, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
766*b7c941bbSAndroid Build Coastguard Worker setSampleInfo(extractor, &currInfo);
767*b7c941bbSAndroid Build Coastguard Worker isPass = isSampleInfoIdentical(&sampleInfoAtZero, &currInfo);
768*b7c941bbSAndroid Build Coastguard Worker if (!isPass) {
769*b7c941bbSAndroid Build Coastguard Worker ALOGE("seen mismatch seekTo(-1, SEEK_TO_CLOSEST_SYNC)");
770*b7c941bbSAndroid Build Coastguard Worker ALOGE(" flags exp/got: %d / %d", sampleInfoAtZero.flags, currInfo.flags);
771*b7c941bbSAndroid Build Coastguard Worker ALOGE(" size exp/got: %d / %d ", sampleInfoAtZero.size, currInfo.size);
772*b7c941bbSAndroid Build Coastguard Worker ALOGE(" ts exp/got: %" PRId64 " / %" PRId64 "",
773*b7c941bbSAndroid Build Coastguard Worker sampleInfoAtZero.presentationTimeUs, currInfo.presentationTimeUs);
774*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
775*b7c941bbSAndroid Build Coastguard Worker break;
776*b7c941bbSAndroid Build Coastguard Worker }
777*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_unselectTrack(extractor, trackID);
778*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
779*b7c941bbSAndroid Build Coastguard Worker }
780*b7c941bbSAndroid Build Coastguard Worker }
781*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_delete(extractor);
782*b7c941bbSAndroid Build Coastguard Worker }
783*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
784*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jMediaType, cMediaType);
785*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcPath, csrcPath);
786*b7c941bbSAndroid Build Coastguard Worker return static_cast<jboolean>(isPass);
787*b7c941bbSAndroid Build Coastguard Worker }
788*b7c941bbSAndroid Build Coastguard Worker
nativeTestFileFormat(JNIEnv * env,jobject,jstring jsrcPath)789*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestFileFormat(JNIEnv* env, jobject, jstring jsrcPath) {
790*b7c941bbSAndroid Build Coastguard Worker bool isPass = false;
791*b7c941bbSAndroid Build Coastguard Worker const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
792*b7c941bbSAndroid Build Coastguard Worker FILE* srcFp = fopen(csrcPath, "rbe");
793*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* extractor = createExtractorFromFD(srcFp);
794*b7c941bbSAndroid Build Coastguard Worker if (extractor) {
795*b7c941bbSAndroid Build Coastguard Worker AMediaFormat* format = AMediaExtractor_getFileFormat(extractor);
796*b7c941bbSAndroid Build Coastguard Worker const char* mediaType = nullptr;
797*b7c941bbSAndroid Build Coastguard Worker bool hasKey = AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mediaType);
798*b7c941bbSAndroid Build Coastguard Worker /* TODO: Not Sure if we need to verify any other parameter of file format */
799*b7c941bbSAndroid Build Coastguard Worker if (hasKey && mediaType && strlen(mediaType) > 0) {
800*b7c941bbSAndroid Build Coastguard Worker isPass = true;
801*b7c941bbSAndroid Build Coastguard Worker }
802*b7c941bbSAndroid Build Coastguard Worker AMediaFormat_delete(format);
803*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor_delete(extractor);
804*b7c941bbSAndroid Build Coastguard Worker }
805*b7c941bbSAndroid Build Coastguard Worker if (srcFp) fclose(srcFp);
806*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcPath, csrcPath);
807*b7c941bbSAndroid Build Coastguard Worker return static_cast<jboolean>(isPass);
808*b7c941bbSAndroid Build Coastguard Worker }
809*b7c941bbSAndroid Build Coastguard Worker
nativeTestDataSource(JNIEnv * env,jobject,jstring jsrcPath,jstring jsrcUrl)810*b7c941bbSAndroid Build Coastguard Worker static jboolean nativeTestDataSource(JNIEnv* env, jobject, jstring jsrcPath, jstring jsrcUrl) {
811*b7c941bbSAndroid Build Coastguard Worker bool isPass = true;
812*b7c941bbSAndroid Build Coastguard Worker const char* csrcUrl = env->GetStringUTFChars(jsrcUrl, nullptr);
813*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* refExtractor = AMediaExtractor_new();
814*b7c941bbSAndroid Build Coastguard Worker media_status_t status = AMediaExtractor_setDataSource(refExtractor, csrcUrl);
815*b7c941bbSAndroid Build Coastguard Worker if (status == AMEDIA_OK) {
816*b7c941bbSAndroid Build Coastguard Worker isPass &= validateCachedDuration(refExtractor, true);
817*b7c941bbSAndroid Build Coastguard Worker const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
818*b7c941bbSAndroid Build Coastguard Worker AMediaDataSource* dataSource = nullptr;
819*b7c941bbSAndroid Build Coastguard Worker AMediaExtractor* testExtractor = nullptr;
820*b7c941bbSAndroid Build Coastguard Worker if (createExtractorFromUrl(env, nullptr, nullptr, &testExtractor, &dataSource, csrcUrl)) {
821*b7c941bbSAndroid Build Coastguard Worker isPass &= validateCachedDuration(testExtractor, true);
822*b7c941bbSAndroid Build Coastguard Worker if (!(isMediaSimilar(refExtractor, testExtractor, nullptr) &&
823*b7c941bbSAndroid Build Coastguard Worker isFileFormatIdentical(refExtractor, testExtractor) &&
824*b7c941bbSAndroid Build Coastguard Worker isSeekOk(refExtractor, testExtractor))) {
825*b7c941bbSAndroid Build Coastguard Worker isPass = false;
826*b7c941bbSAndroid Build Coastguard Worker }
827*b7c941bbSAndroid Build Coastguard Worker }
828*b7c941bbSAndroid Build Coastguard Worker if (testExtractor) AMediaExtractor_delete(testExtractor);
829*b7c941bbSAndroid Build Coastguard Worker if (dataSource) AMediaDataSource_delete(dataSource);
830*b7c941bbSAndroid Build Coastguard Worker
831*b7c941bbSAndroid Build Coastguard Worker FILE* testFp = fopen(csrcPath, "rbe");
832*b7c941bbSAndroid Build Coastguard Worker testExtractor = createExtractorFromFD(testFp);
833*b7c941bbSAndroid Build Coastguard Worker if (testExtractor == nullptr) {
834*b7c941bbSAndroid Build Coastguard Worker ALOGE("createExtractorFromFD failed for test extractor");
835*b7c941bbSAndroid Build Coastguard Worker isPass = false;
836*b7c941bbSAndroid Build Coastguard Worker } else {
837*b7c941bbSAndroid Build Coastguard Worker isPass &= validateCachedDuration(testExtractor, false);
838*b7c941bbSAndroid Build Coastguard Worker if (!(isMediaSimilar(refExtractor, testExtractor, nullptr) &&
839*b7c941bbSAndroid Build Coastguard Worker isFileFormatIdentical(refExtractor, testExtractor) &&
840*b7c941bbSAndroid Build Coastguard Worker isSeekOk(refExtractor, testExtractor))) {
841*b7c941bbSAndroid Build Coastguard Worker isPass = false;
842*b7c941bbSAndroid Build Coastguard Worker }
843*b7c941bbSAndroid Build Coastguard Worker }
844*b7c941bbSAndroid Build Coastguard Worker if (testExtractor) AMediaExtractor_delete(testExtractor);
845*b7c941bbSAndroid Build Coastguard Worker if (testFp) fclose(testFp);
846*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcPath, csrcPath);
847*b7c941bbSAndroid Build Coastguard Worker } else {
848*b7c941bbSAndroid Build Coastguard Worker ALOGE("setDataSource failed");
849*b7c941bbSAndroid Build Coastguard Worker isPass = false;
850*b7c941bbSAndroid Build Coastguard Worker }
851*b7c941bbSAndroid Build Coastguard Worker if (refExtractor) AMediaExtractor_delete(refExtractor);
852*b7c941bbSAndroid Build Coastguard Worker env->ReleaseStringUTFChars(jsrcUrl, csrcUrl);
853*b7c941bbSAndroid Build Coastguard Worker return static_cast<jboolean>(isPass);
854*b7c941bbSAndroid Build Coastguard Worker }
855*b7c941bbSAndroid Build Coastguard Worker
registerAndroidMediaV2CtsExtractorTestSetDS(JNIEnv * env)856*b7c941bbSAndroid Build Coastguard Worker int registerAndroidMediaV2CtsExtractorTestSetDS(JNIEnv* env) {
857*b7c941bbSAndroid Build Coastguard Worker const JNINativeMethod methodTable[] = {
858*b7c941bbSAndroid Build Coastguard Worker {"nativeTestDataSource", "(Ljava/lang/String;Ljava/lang/String;)Z",
859*b7c941bbSAndroid Build Coastguard Worker (void*)nativeTestDataSource},
860*b7c941bbSAndroid Build Coastguard Worker };
861*b7c941bbSAndroid Build Coastguard Worker jclass c = env->FindClass("android/mediav2/cts/ExtractorTest$SetDataSourceTest");
862*b7c941bbSAndroid Build Coastguard Worker return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
863*b7c941bbSAndroid Build Coastguard Worker }
864*b7c941bbSAndroid Build Coastguard Worker
registerAndroidMediaV2CtsExtractorTestFunc(JNIEnv * env)865*b7c941bbSAndroid Build Coastguard Worker int registerAndroidMediaV2CtsExtractorTestFunc(JNIEnv* env) {
866*b7c941bbSAndroid Build Coastguard Worker const JNINativeMethod methodTable[] = {
867*b7c941bbSAndroid Build Coastguard Worker {"nativeTestExtract", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
868*b7c941bbSAndroid Build Coastguard Worker (void*)nativeTestExtract},
869*b7c941bbSAndroid Build Coastguard Worker {"nativeTestSeek", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)nativeTestSeek},
870*b7c941bbSAndroid Build Coastguard Worker {"nativeTestSeekFlakiness", "(Ljava/lang/String;Ljava/lang/String;)Z",
871*b7c941bbSAndroid Build Coastguard Worker (void*)nativeTestSeekFlakiness},
872*b7c941bbSAndroid Build Coastguard Worker {"nativeTestSeekToZero", "(Ljava/lang/String;Ljava/lang/String;)Z",
873*b7c941bbSAndroid Build Coastguard Worker (void*)nativeTestSeekToZero},
874*b7c941bbSAndroid Build Coastguard Worker {"nativeTestFileFormat", "(Ljava/lang/String;)Z", (void*)nativeTestFileFormat},
875*b7c941bbSAndroid Build Coastguard Worker };
876*b7c941bbSAndroid Build Coastguard Worker jclass c = env->FindClass("android/mediav2/cts/ExtractorTest$FunctionalityTest");
877*b7c941bbSAndroid Build Coastguard Worker return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
878*b7c941bbSAndroid Build Coastguard Worker }
879*b7c941bbSAndroid Build Coastguard Worker
registerAndroidMediaV2CtsExtractorTest(JNIEnv * env)880*b7c941bbSAndroid Build Coastguard Worker int registerAndroidMediaV2CtsExtractorTest(JNIEnv* env) {
881*b7c941bbSAndroid Build Coastguard Worker const JNINativeMethod methodTable[] = {
882*b7c941bbSAndroid Build Coastguard Worker {"nativeReadAllData",
883*b7c941bbSAndroid Build Coastguard Worker "(Ljava/lang/String;Ljava/lang/String;I[Ljava/lang/String;[Ljava/lang/String;Z)J",
884*b7c941bbSAndroid Build Coastguard Worker (void*)nativeReadAllData},
885*b7c941bbSAndroid Build Coastguard Worker };
886*b7c941bbSAndroid Build Coastguard Worker jclass c = env->FindClass("android/mediav2/cts/ExtractorTest");
887*b7c941bbSAndroid Build Coastguard Worker return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
888*b7c941bbSAndroid Build Coastguard Worker }
889*b7c941bbSAndroid Build Coastguard Worker
890*b7c941bbSAndroid Build Coastguard Worker extern int registerAndroidMediaV2CtsExtractorUnitTestApi(JNIEnv* env);
891*b7c941bbSAndroid Build Coastguard Worker
JNI_OnLoad(JavaVM * vm,void *)892*b7c941bbSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
893*b7c941bbSAndroid Build Coastguard Worker JNIEnv* env;
894*b7c941bbSAndroid Build Coastguard Worker if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) return JNI_ERR;
895*b7c941bbSAndroid Build Coastguard Worker if (registerAndroidMediaV2CtsExtractorTest(env) != JNI_OK) return JNI_ERR;
896*b7c941bbSAndroid Build Coastguard Worker if (registerAndroidMediaV2CtsExtractorTestSetDS(env) != JNI_OK) return JNI_ERR;
897*b7c941bbSAndroid Build Coastguard Worker if (registerAndroidMediaV2CtsExtractorTestFunc(env) != JNI_OK) return JNI_ERR;
898*b7c941bbSAndroid Build Coastguard Worker if (registerAndroidMediaV2CtsExtractorUnitTestApi(env) != JNI_OK) return JNI_ERR;
899*b7c941bbSAndroid Build Coastguard Worker return JNI_VERSION_1_6;
900*b7c941bbSAndroid Build Coastguard Worker }
901