1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "NativeExtractorUnitTest"
19 #include <log/log.h>
20
21 #include <NdkMediaExtractor.h>
22 #include <jni.h>
23 #include <sys/stat.h>
24
25 #include <cstdlib>
26 #include <cstring>
27
setExtractorDataSource(AMediaExtractor * extractor,FILE * fp)28 static media_status_t setExtractorDataSource(AMediaExtractor* extractor, FILE* fp) {
29 media_status_t status = AMEDIA_ERROR_BASE;
30 struct stat buf {};
31 if (fp && !fstat(fileno(fp), &buf))
32 status = AMediaExtractor_setDataSourceFd(extractor, fileno(fp), 0, buf.st_size);
33 if (status != AMEDIA_OK) ALOGE("error: AMediaExtractor_setDataSourceFd failed %d", status);
34 return status;
35 }
36
nativeTestGetTrackCountBeforeSetDataSource(JNIEnv *,jobject)37 static jboolean nativeTestGetTrackCountBeforeSetDataSource(JNIEnv*, jobject) {
38 AMediaExtractor* extractor = AMediaExtractor_new();
39 bool isPass = (0 == AMediaExtractor_getTrackCount(extractor));
40 if (!isPass) ALOGE("error: received valid trackCount before setDataSource");
41 AMediaExtractor_delete(extractor);
42 return static_cast<jboolean>(isPass);
43 }
44
nativeTestSelectTrackBeforeSetDataSource(JNIEnv *,jobject)45 static jboolean nativeTestSelectTrackBeforeSetDataSource(JNIEnv*, jobject) {
46 AMediaExtractor* extractor = AMediaExtractor_new();
47 bool isPass = (AMEDIA_OK != AMediaExtractor_selectTrack(extractor, 0));
48 if (!isPass) ALOGE("error: selectTrack succeeds before setDataSource");
49 AMediaExtractor_delete(extractor);
50 return static_cast<jboolean>(isPass);
51 }
52
nativeTestSelectTrackForInvalidIndex(JNIEnv * env,jobject,jstring jsrcPath)53 static jboolean nativeTestSelectTrackForInvalidIndex(JNIEnv* env, jobject, jstring jsrcPath) {
54 bool isPass = false;
55 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
56 AMediaExtractor* extractor = AMediaExtractor_new();
57 FILE* srcFp = fopen(csrcPath, "rbe");
58 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
59 if (AMEDIA_OK !=
60 AMediaExtractor_selectTrack(extractor, AMediaExtractor_getTrackCount(extractor))) {
61 isPass = true;
62 } else {
63 ALOGE("error: selectTrack succeeds for out of bounds track index: %zu",
64 AMediaExtractor_getTrackCount(extractor));
65 }
66 }
67 AMediaExtractor_delete(extractor);
68 if (srcFp) fclose(srcFp);
69 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
70 return static_cast<jboolean>(isPass);
71 }
72
nativeTestIdempotentSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)73 static jboolean nativeTestIdempotentSelectTrack(JNIEnv* env, jobject, jstring jsrcPath) {
74 bool isPass = false;
75 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
76 AMediaExtractor* extractor = AMediaExtractor_new();
77 FILE* srcFp = fopen(csrcPath, "rbe");
78 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
79 isPass = AMediaExtractor_selectTrack(extractor, 0) == AMEDIA_OK;
80 isPass &= AMediaExtractor_selectTrack(extractor, 0) == AMEDIA_OK;
81 if (!isPass) ALOGE("error: multiple selection of same track has failed");
82 }
83 AMediaExtractor_delete(extractor);
84 if (srcFp) fclose(srcFp);
85 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
86 return static_cast<jboolean>(isPass);
87 }
88
nativeTestUnselectTrackBeforeSetDataSource(JNIEnv *,jobject)89 static jboolean nativeTestUnselectTrackBeforeSetDataSource(JNIEnv*, jobject) {
90 AMediaExtractor* extractor = AMediaExtractor_new();
91 bool isPass = (AMEDIA_OK != AMediaExtractor_unselectTrack(extractor, 0));
92 if (!isPass) ALOGE("error: unselectTrack succeeds before setDataSource");
93 AMediaExtractor_delete(extractor);
94 return static_cast<jboolean>(isPass);
95 }
96
nativeTestUnselectTrackForInvalidIndex(JNIEnv * env,jobject,jstring jsrcPath)97 static jboolean nativeTestUnselectTrackForInvalidIndex(JNIEnv* env, jobject, jstring jsrcPath) {
98 bool isPass = false;
99 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
100 AMediaExtractor* extractor = AMediaExtractor_new();
101 FILE* srcFp = fopen(csrcPath, "rbe");
102 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
103 if (AMEDIA_OK !=
104 AMediaExtractor_unselectTrack(extractor, AMediaExtractor_getTrackCount(extractor))) {
105 isPass = true;
106 } else {
107 ALOGE("error: unselectTrack succeeds for out of bounds track index: %zu",
108 AMediaExtractor_getTrackCount(extractor));
109 }
110 }
111 AMediaExtractor_delete(extractor);
112 if (srcFp) fclose(srcFp);
113 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
114 return static_cast<jboolean>(isPass);
115 }
116
nativeTestUnselectTrackForUnSelectedTrackIndex(JNIEnv * env,jobject,jstring jsrcPath)117 static jboolean nativeTestUnselectTrackForUnSelectedTrackIndex(JNIEnv* env, jobject,
118 jstring jsrcPath) {
119 bool isPass = false;
120 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
121 AMediaExtractor* extractor = AMediaExtractor_new();
122 FILE* srcFp = fopen(csrcPath, "rbe");
123 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
124 isPass = (AMediaExtractor_unselectTrack(extractor, 0) == AMEDIA_OK);
125 if (!isPass) ALOGE("error: un-selection of non-selected track has failed");
126 }
127 AMediaExtractor_delete(extractor);
128 if (srcFp) fclose(srcFp);
129 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
130 return static_cast<jboolean>(isPass);
131 }
132
nativeTestIdempotentUnselectTrack(JNIEnv * env,jobject,jstring jsrcPath)133 static jboolean nativeTestIdempotentUnselectTrack(JNIEnv* env, jobject, jstring jsrcPath) {
134 bool isPass = false;
135 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
136 AMediaExtractor* extractor = AMediaExtractor_new();
137 FILE* srcFp = fopen(csrcPath, "rbe");
138 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
139 isPass = AMediaExtractor_selectTrack(extractor, 0) == AMEDIA_OK;
140 if (isPass) {
141 isPass = AMediaExtractor_unselectTrack(extractor, 0) == AMEDIA_OK;
142 isPass &= AMediaExtractor_unselectTrack(extractor, 0) == AMEDIA_OK;
143 if (!isPass) ALOGE("error: multiple unselection of selected track has failed");
144 } else {
145 ALOGE("error: selection of track 0 has failed for file %s", csrcPath);
146 }
147 }
148 AMediaExtractor_delete(extractor);
149 if (srcFp) fclose(srcFp);
150 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
151 return static_cast<jboolean>(isPass);
152 }
153
nativeTestSeekToBeforeSetDataSource(JNIEnv *,jobject)154 static jboolean nativeTestSeekToBeforeSetDataSource(JNIEnv*, jobject) {
155 AMediaExtractor* extractor = AMediaExtractor_new();
156 bool isPass = AMediaExtractor_seekTo(extractor, 0, AMEDIAEXTRACTOR_SEEK_NEXT_SYNC) != AMEDIA_OK;
157 if (!isPass) ALOGE("error: seekTo() succeeds before setting data source");
158 AMediaExtractor_delete(extractor);
159 return static_cast<jboolean>(isPass);
160 }
161
nativeTestSeekToBeforeSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)162 static jboolean nativeTestSeekToBeforeSelectTrack(JNIEnv* env, jobject, jstring jsrcPath) {
163 bool isPass = false;
164 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
165 AMediaExtractor* extractor = AMediaExtractor_new();
166 FILE* srcFp = fopen(csrcPath, "rbe");
167 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
168 isPass = AMediaExtractor_seekTo(extractor, 0, AMEDIAEXTRACTOR_SEEK_NEXT_SYNC) != AMEDIA_OK;
169 if (!isPass) ALOGE("error: seekTo() succeeds before selecting track");
170 }
171 AMediaExtractor_delete(extractor);
172 if (srcFp) fclose(srcFp);
173 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
174 return static_cast<jboolean>(isPass);
175 }
176
nativeTestGetCachedDurationBeforeSetDataSource(JNIEnv *,jobject)177 static jboolean nativeTestGetCachedDurationBeforeSetDataSource(JNIEnv*, jobject) {
178 AMediaExtractor* extractor = AMediaExtractor_new();
179 bool isPass = AMediaExtractor_getCachedDuration(extractor) == -1;
180 if (!isPass) ALOGE("error: getCachedDuration returns unexpected value before setDataSource");
181 AMediaExtractor_delete(extractor);
182 return static_cast<jboolean>(isPass);
183 }
184
nativeTestIfGetFileFormatSucceedsBeforeSetDataSource(JNIEnv *,jobject)185 static jboolean nativeTestIfGetFileFormatSucceedsBeforeSetDataSource(JNIEnv*, jobject) {
186 AMediaExtractor* extractor = AMediaExtractor_new();
187 AMediaFormat* empty = AMediaFormat_new();
188 AMediaFormat* format = AMediaExtractor_getFileFormat(extractor);
189 bool isPass = true;
190 if (format == nullptr ||
191 strcmp(AMediaFormat_toString(empty), AMediaFormat_toString(format)) != 0) {
192 isPass = false;
193 ALOGE("error: getFileFormat before set data source yields unexpected result");
194 }
195 if (format) AMediaFormat_delete(format);
196 AMediaFormat_delete(empty);
197 AMediaExtractor_delete(extractor);
198 return static_cast<jboolean>(isPass);
199 }
200
nativeTestAdvanceBeforeSetDataSource(JNIEnv *,jobject)201 static jboolean nativeTestAdvanceBeforeSetDataSource(JNIEnv*, jobject) {
202 AMediaExtractor* extractor = AMediaExtractor_new();
203 bool isPass = !AMediaExtractor_advance(extractor);
204 if (!isPass) ALOGE("error: advance succeeds before setDataSource");
205 AMediaExtractor_delete(extractor);
206 return static_cast<jboolean>(isPass);
207 }
208
nativeTestAdvanceBeforeSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)209 static jboolean nativeTestAdvanceBeforeSelectTrack(JNIEnv* env, jobject, jstring jsrcPath) {
210 bool isPass = false;
211 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
212 AMediaExtractor* extractor = AMediaExtractor_new();
213 FILE* srcFp = fopen(csrcPath, "rbe");
214 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
215 isPass = !AMediaExtractor_advance(extractor);
216 if (!isPass) ALOGE("error: advance succeeds without any active tracks");
217 }
218 AMediaExtractor_delete(extractor);
219 if (srcFp) fclose(srcFp);
220 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
221 return static_cast<jboolean>(isPass);
222 }
223
nativeTestGetSampleFlagsBeforeSetDataSource(JNIEnv *,jobject)224 static jboolean nativeTestGetSampleFlagsBeforeSetDataSource(JNIEnv*, jobject) {
225 AMediaExtractor* extractor = AMediaExtractor_new();
226 bool isPass = AMediaExtractor_getSampleFlags(extractor) == -1;
227 if (!isPass) ALOGE("error: received valid sample flag before setDataSource");
228 AMediaExtractor_delete(extractor);
229 return static_cast<jboolean>(isPass);
230 }
231
nativeTestGetSampleFlagsBeforeSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)232 static jboolean nativeTestGetSampleFlagsBeforeSelectTrack(JNIEnv* env, jobject, jstring jsrcPath) {
233 bool isPass = false;
234 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
235 AMediaExtractor* extractor = AMediaExtractor_new();
236 FILE* srcFp = fopen(csrcPath, "rbe");
237 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
238 isPass = AMediaExtractor_getSampleFlags(extractor) == -1;
239 if (!isPass) ALOGE("error: received valid sample flag without any active tracks");
240 }
241 AMediaExtractor_delete(extractor);
242 if (srcFp) fclose(srcFp);
243 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
244 return static_cast<jboolean>(isPass);
245 }
246
nativeTestGetSampleTimeBeforeSetDataSource(JNIEnv *,jobject)247 static jboolean nativeTestGetSampleTimeBeforeSetDataSource(JNIEnv*, jobject) {
248 AMediaExtractor* extractor = AMediaExtractor_new();
249 bool isPass = AMediaExtractor_getSampleTime(extractor) == -1;
250 if (!isPass) ALOGE("error: received valid pts before setDataSource");
251 AMediaExtractor_delete(extractor);
252 return static_cast<jboolean>(isPass);
253 }
254
nativeTestGetSampleTimeBeforeSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)255 static jboolean nativeTestGetSampleTimeBeforeSelectTrack(JNIEnv* env, jobject, jstring jsrcPath) {
256 bool isPass = false;
257 AMediaExtractor* extractor = AMediaExtractor_new();
258 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
259 FILE* srcFp = fopen(csrcPath, "rbe");
260 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
261 isPass = AMediaExtractor_getSampleTime(extractor) == -1;
262 if (!isPass) ALOGE("error: received valid pts without any active tracks");
263 }
264 AMediaExtractor_delete(extractor);
265 if (srcFp) fclose(srcFp);
266 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
267 return static_cast<jboolean>(isPass);
268 }
269
nativeTestGetSampleSizeBeforeSetDataSource(JNIEnv *,jobject)270 static jboolean nativeTestGetSampleSizeBeforeSetDataSource(JNIEnv*, jobject) {
271 AMediaExtractor* extractor = AMediaExtractor_new();
272 bool isPass = AMediaExtractor_getSampleSize(extractor) == -1;
273 if (!isPass) ALOGE("error: received valid sample size before setDataSource");
274 AMediaExtractor_delete(extractor);
275 return static_cast<jboolean>(isPass);
276 }
277
nativeTestGetSampleSizeBeforeSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)278 static jboolean nativeTestGetSampleSizeBeforeSelectTrack(JNIEnv* env, jobject, jstring jsrcPath) {
279 bool isPass = false;
280 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
281 AMediaExtractor* extractor = AMediaExtractor_new();
282 FILE* srcFp = fopen(csrcPath, "rbe");
283 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
284 isPass = AMediaExtractor_getSampleSize(extractor) == -1;
285 if (!isPass) ALOGE("error: received valid sample size without any active tracks");
286 }
287 AMediaExtractor_delete(extractor);
288 if (srcFp) fclose(srcFp);
289 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
290 return static_cast<jboolean>(isPass);
291 }
292
nativeTestIfGetSampleFormatBeforeSetDataSource(JNIEnv *,jobject)293 static jboolean nativeTestIfGetSampleFormatBeforeSetDataSource(JNIEnv*, jobject) {
294 AMediaExtractor* extractor = AMediaExtractor_new();
295 AMediaFormat* format = AMediaFormat_new();
296 bool isPass = AMediaExtractor_getSampleFormat(extractor, format) != AMEDIA_OK;
297 if (!isPass) ALOGE("error: getSampleFormat succeeds before setDataSource");
298 AMediaFormat_delete(format);
299 AMediaExtractor_delete(extractor);
300 return static_cast<jboolean>(isPass);
301 }
302
nativeTestIfGetSampleFormatBeforeSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)303 static jboolean nativeTestIfGetSampleFormatBeforeSelectTrack(JNIEnv* env, jobject,
304 jstring jsrcPath) {
305 bool isPass = false;
306 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
307 AMediaExtractor* extractor = AMediaExtractor_new();
308 AMediaFormat* format = AMediaFormat_new();
309 FILE* srcFp = fopen(csrcPath, "rbe");
310 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
311 isPass = AMediaExtractor_getSampleFormat(extractor, format) != AMEDIA_OK;
312 if (!isPass) ALOGE("error: getSampleFormat succeeds without any active tracks");
313 }
314 AMediaFormat_delete(format);
315 AMediaExtractor_delete(extractor);
316 if (srcFp) fclose(srcFp);
317 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
318 return static_cast<jboolean>(isPass);
319 }
320
nativeTestVideoSampleFileOffsetByGetSampleFormat(JNIEnv * env,jobject,jstring jsrcPath)321 static jboolean nativeTestVideoSampleFileOffsetByGetSampleFormat(JNIEnv* env, jobject,
322 jstring jsrcPath) {
323 int64_t video_sample_offsets[] = {6522, 95521, 118719, 126219, 137578};
324 bool isPass = true;
325 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
326 AMediaExtractor* extractor = AMediaExtractor_new();
327 AMediaFormat* format = AMediaFormat_new();
328 FILE* srcFp = fopen(csrcPath, "rbe");
329 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
330 if (AMEDIA_OK == AMediaExtractor_selectTrack(extractor, 0 /* video */)) {
331 for(int i = 0; i < sizeof(video_sample_offsets)/sizeof(int64_t); ++i) {
332 if (AMEDIA_OK == AMediaExtractor_getSampleFormat(extractor, format)) {
333 ALOGV("AMediaFormat_toString:%s", AMediaFormat_toString(format));
334 int64_t offset = 0;
335 if (AMediaFormat_getInt64(format, "sample-file-offset", &offset)) {
336 if (offset != video_sample_offsets[i]) {
337 ALOGD("offset:%lld, video_sample_offsets[%d]:%lld",
338 (long long)offset, i, (long long)video_sample_offsets[i]);
339 isPass = false;
340 break;
341 }
342 } else {
343 ALOGD("error: sample-file-offset not found");
344 isPass = false;
345 break;
346 }
347 }
348 AMediaExtractor_advance(extractor);
349 }
350 }
351 }
352 AMediaExtractor_delete(extractor);
353 AMediaFormat_delete(format);
354 if (srcFp) fclose(srcFp);
355 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
356 return static_cast<jboolean>(isPass);
357 }
358
nativeTestAudioSampleFileOffsetByGetSampleFormat(JNIEnv * env,jobject,jstring jsrcPath)359 static jboolean nativeTestAudioSampleFileOffsetByGetSampleFormat(JNIEnv* env, jobject,
360 jstring jsrcPath) {
361 int64_t audio_sample_offsets[] = {186125, 186682, 187286, 187944, 188551};
362 bool isPass = true;
363 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
364 AMediaExtractor* extractor = AMediaExtractor_new();
365 AMediaFormat* format = AMediaFormat_new();
366 FILE* srcFp = fopen(csrcPath, "rbe");
367 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
368 if (AMEDIA_OK == AMediaExtractor_selectTrack(extractor, 1 /* audio */)) {
369 for(int i = 0; i < sizeof(audio_sample_offsets)/sizeof(int64_t); ++i) {
370 if (AMEDIA_OK == AMediaExtractor_getSampleFormat(extractor, format)) {
371 ALOGV("AMediaFormat_toString:%s", AMediaFormat_toString(format));
372 int64_t offset = 0;
373 if (AMediaFormat_getInt64(format, "sample-file-offset", &offset)) {
374 if (offset != audio_sample_offsets[i]) {
375 ALOGD("offset:%lld, audio_sample_offsets[%d]:%lld",
376 (long long)offset, i, (long long)audio_sample_offsets[i]);
377 isPass = false;
378 break;
379 }
380 } else {
381 ALOGE("error: sample-file-offset not found");
382 isPass = false;
383 break;
384 }
385 }
386 AMediaExtractor_advance(extractor);
387 }
388 }
389 }
390 AMediaExtractor_delete(extractor);
391 AMediaFormat_delete(format);
392 if (srcFp) fclose(srcFp);
393 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
394 return static_cast<jboolean>(isPass);
395 }
396
nativeTestGetSampleTrackIndexBeforeSetDataSource(JNIEnv *,jobject)397 static jboolean nativeTestGetSampleTrackIndexBeforeSetDataSource(JNIEnv*, jobject) {
398 AMediaExtractor* extractor = AMediaExtractor_new();
399 bool isPass = AMediaExtractor_getSampleTrackIndex(extractor) == -1;
400 if (!isPass) ALOGE("error: received valid track index before setDataSource");
401 AMediaExtractor_delete(extractor);
402 return static_cast<jboolean>(isPass);
403 }
404
nativeTestGetSampleTrackIndexBeforeSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)405 static jboolean nativeTestGetSampleTrackIndexBeforeSelectTrack(JNIEnv* env, jobject,
406 jstring jsrcPath) {
407 bool isPass = false;
408 AMediaExtractor* extractor = AMediaExtractor_new();
409 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
410 FILE* srcFp = fopen(csrcPath, "rbe");
411 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
412 isPass = AMediaExtractor_getSampleTrackIndex(extractor) == -1;
413 if (!isPass) ALOGE("error: received valid track index without any active tracks");
414 }
415 AMediaExtractor_delete(extractor);
416 if (srcFp) fclose(srcFp);
417 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
418 return static_cast<jboolean>(isPass);
419 }
420
nativeTestGetTrackFormatBeforeSetDataSource(JNIEnv *,jobject)421 static jboolean nativeTestGetTrackFormatBeforeSetDataSource(JNIEnv*, jobject) {
422 bool isPass = true;
423 AMediaExtractor* extractor = AMediaExtractor_new();
424 AMediaFormat* empty = AMediaFormat_new();
425 AMediaFormat* format = AMediaExtractor_getTrackFormat(extractor, 0);
426 if (format == nullptr ||
427 strcmp(AMediaFormat_toString(empty), AMediaFormat_toString(format)) != 0) {
428 isPass = false;
429 ALOGE("error: getTrackFormat before setDataSource yields unexpected result");
430 }
431 if (format) AMediaFormat_delete(format);
432 AMediaFormat_delete(empty);
433 AMediaExtractor_delete(extractor);
434 return static_cast<jboolean>(isPass);
435 }
436
nativeTestGetTrackFormatForInvalidIndex(JNIEnv * env,jobject,jstring jsrcPath)437 static jboolean nativeTestGetTrackFormatForInvalidIndex(JNIEnv* env, jobject, jstring jsrcPath) {
438 bool isPass = true;
439 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
440 AMediaExtractor* extractor = AMediaExtractor_new();
441 FILE* srcFp = fopen(csrcPath, "rbe");
442 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
443 AMediaFormat* format =
444 AMediaExtractor_getTrackFormat(extractor, AMediaExtractor_getTrackCount(extractor));
445 AMediaFormat* empty = AMediaFormat_new();
446 if (format == nullptr ||
447 strcmp(AMediaFormat_toString(empty), AMediaFormat_toString(format)) != 0) {
448 isPass = false;
449 ALOGE("error: getTrackFormat for out of bound track index %zu yields unexpected result",
450 AMediaExtractor_getTrackCount(extractor));
451 }
452 if (format) AMediaFormat_delete(format);
453 AMediaFormat_delete(empty);
454 } else {
455 isPass = false;
456 }
457 AMediaExtractor_delete(extractor);
458 if (srcFp) fclose(srcFp);
459 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
460 return static_cast<jboolean>(isPass);
461 }
462
nativeTestReadSampleDataBeforeSetDataSource(JNIEnv *,jobject)463 static jboolean nativeTestReadSampleDataBeforeSetDataSource(JNIEnv*, jobject) {
464 AMediaExtractor* extractor = AMediaExtractor_new();
465 const int maxSampleSize = 512 * 1024;
466 auto buffer = new uint8_t[maxSampleSize];
467 bool isPass = AMediaExtractor_readSampleData(extractor, buffer, maxSampleSize) < 0;
468 if (!isPass) ALOGE("error: readSampleData return non-negative readBytes before setDataSource");
469 delete[] buffer;
470 AMediaExtractor_delete(extractor);
471 return static_cast<jboolean>(isPass);
472 }
473
nativeTestReadSampleDataBeforeSelectTrack(JNIEnv * env,jobject,jstring jsrcPath)474 static jboolean nativeTestReadSampleDataBeforeSelectTrack(JNIEnv* env, jobject, jstring jsrcPath) {
475 bool isPass = false;
476 const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
477 AMediaExtractor* extractor = AMediaExtractor_new();
478 const int maxSampleSize = (512 * 1024);
479 auto buffer = new uint8_t[maxSampleSize];
480 FILE* srcFp = fopen(csrcPath, "rbe");
481 if (AMEDIA_OK == setExtractorDataSource(extractor, srcFp)) {
482 isPass = AMediaExtractor_readSampleData(extractor, buffer, maxSampleSize) < 0;
483 if (!isPass) {
484 ALOGE("error: readSampleData returns non-negative readBytes with out active tracks");
485 }
486 }
487 delete[] buffer;
488 AMediaExtractor_delete(extractor);
489 if (srcFp) fclose(srcFp);
490 env->ReleaseStringUTFChars(jsrcPath, csrcPath);
491 return static_cast<jboolean>(isPass);
492 }
493
nativeTestIfNullLocationIsRejectedBySetDataSource(JNIEnv *,jobject)494 static jboolean nativeTestIfNullLocationIsRejectedBySetDataSource(JNIEnv*, jobject) {
495 AMediaExtractor* extractor = AMediaExtractor_new();
496 bool isPass = AMediaExtractor_setDataSource(extractor, nullptr) != AMEDIA_OK;
497 if (!isPass) ALOGE("error: setDataSource succeeds with null location");
498 AMediaExtractor_delete(extractor);
499 return static_cast<jboolean>(isPass);
500 }
501
registerAndroidMediaV2CtsExtractorUnitTestApi(JNIEnv * env)502 int registerAndroidMediaV2CtsExtractorUnitTestApi(JNIEnv* env) {
503 const JNINativeMethod methodTable[] = {
504 {"nativeTestGetTrackCountBeforeSetDataSource", "()Z",
505 (void*)nativeTestGetTrackCountBeforeSetDataSource},
506 {"nativeTestSelectTrackBeforeSetDataSource", "()Z",
507 (void*)nativeTestSelectTrackBeforeSetDataSource},
508 {"nativeTestSelectTrackForInvalidIndex", "(Ljava/lang/String;)Z",
509 (void*)nativeTestSelectTrackForInvalidIndex},
510 {"nativeTestIdempotentSelectTrack", "(Ljava/lang/String;)Z",
511 (void*)nativeTestIdempotentSelectTrack},
512 {"nativeTestUnselectTrackBeforeSetDataSource", "()Z",
513 (void*)nativeTestUnselectTrackBeforeSetDataSource},
514 {"nativeTestUnselectTrackForInvalidIndex", "(Ljava/lang/String;)Z",
515 (void*)nativeTestUnselectTrackForInvalidIndex},
516 {"nativeTestUnselectTrackForUnSelectedTrackIndex", "(Ljava/lang/String;)Z",
517 (void*)nativeTestUnselectTrackForUnSelectedTrackIndex},
518 {"nativeTestIdempotentUnselectTrack", "(Ljava/lang/String;)Z",
519 (void*)nativeTestIdempotentUnselectTrack},
520 {"nativeTestSeekToBeforeSetDataSource", "()Z",
521 (void*)nativeTestSeekToBeforeSetDataSource},
522 {"nativeTestSeekToBeforeSelectTrack", "(Ljava/lang/String;)Z",
523 (void*)nativeTestSeekToBeforeSelectTrack},
524 {"nativeTestGetCachedDurationBeforeSetDataSource", "()Z",
525 (void*)nativeTestGetCachedDurationBeforeSetDataSource},
526 {"nativeTestIfGetFileFormatSucceedsBeforeSetDataSource", "()Z",
527 (void*)nativeTestIfGetFileFormatSucceedsBeforeSetDataSource},
528 {"nativeTestAdvanceBeforeSetDataSource", "()Z",
529 (void*)nativeTestAdvanceBeforeSetDataSource},
530 {"nativeTestAdvanceBeforeSelectTrack", "(Ljava/lang/String;)Z",
531 (void*)nativeTestAdvanceBeforeSelectTrack},
532 {"nativeTestGetSampleFlagsBeforeSetDataSource", "()Z",
533 (void*)nativeTestGetSampleFlagsBeforeSetDataSource},
534 {"nativeTestGetSampleFlagsBeforeSelectTrack", "(Ljava/lang/String;)Z",
535 (void*)nativeTestGetSampleFlagsBeforeSelectTrack},
536 {"nativeTestGetSampleTimeBeforeSetDataSource", "()Z",
537 (void*)nativeTestGetSampleTimeBeforeSetDataSource},
538 {"nativeTestGetSampleTimeBeforeSelectTrack", "(Ljava/lang/String;)Z",
539 (void*)nativeTestGetSampleTimeBeforeSelectTrack},
540 {"nativeTestGetSampleSizeBeforeSetDataSource", "()Z",
541 (void*)nativeTestGetSampleSizeBeforeSetDataSource},
542 {"nativeTestGetSampleSizeBeforeSelectTrack", "(Ljava/lang/String;)Z",
543 (void*)nativeTestGetSampleSizeBeforeSelectTrack},
544 {"nativeTestIfGetSampleFormatBeforeSetDataSource", "()Z",
545 (void*)nativeTestIfGetSampleFormatBeforeSetDataSource},
546 {"nativeTestIfGetSampleFormatBeforeSelectTrack", "(Ljava/lang/String;)Z",
547 (void*)nativeTestIfGetSampleFormatBeforeSelectTrack},
548 {"nativeTestGetSampleTrackIndexBeforeSetDataSource", "()Z",
549 (void*)nativeTestGetSampleTrackIndexBeforeSetDataSource},
550 {"nativeTestGetSampleTrackIndexBeforeSelectTrack", "(Ljava/lang/String;)Z",
551 (void*)nativeTestGetSampleTrackIndexBeforeSelectTrack},
552 {"nativeTestGetTrackFormatBeforeSetDataSource", "()Z",
553 (void*)nativeTestGetTrackFormatBeforeSetDataSource},
554 {"nativeTestGetTrackFormatForInvalidIndex", "(Ljava/lang/String;)Z",
555 (void*)nativeTestGetTrackFormatForInvalidIndex},
556 {"nativeTestReadSampleDataBeforeSetDataSource", "()Z",
557 (void*)nativeTestReadSampleDataBeforeSetDataSource},
558 {"nativeTestReadSampleDataBeforeSelectTrack", "(Ljava/lang/String;)Z",
559 (void*)nativeTestReadSampleDataBeforeSelectTrack},
560 {"nativeTestIfNullLocationIsRejectedBySetDataSource", "()Z",
561 (void*)nativeTestIfNullLocationIsRejectedBySetDataSource},
562 {"nativeTestVideoSampleFileOffsetByGetSampleFormat", "(Ljava/lang/String;)Z",
563 (void*)nativeTestVideoSampleFileOffsetByGetSampleFormat},
564 {"nativeTestAudioSampleFileOffsetByGetSampleFormat", "(Ljava/lang/String;)Z",
565 (void*)nativeTestAudioSampleFileOffsetByGetSampleFormat},
566 };
567 jclass c = env->FindClass("android/mediav2/cts/ExtractorUnitTest$TestApiNative");
568 return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
569 }
570