blob: cbfc9c65dfdf354803483b9b38aba0a5af0b0512 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.mediav2.cts;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.MediaCodec;
import android.media.MediaDataSource;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.util.Log;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
class TestMediaDataSource extends MediaDataSource {
private static final String LOG_TAG = TestMediaDataSource.class.getSimpleName();
private static final boolean ENABLE_LOGS = false;
private byte[] mData;
private boolean mFatalGetSize;
private boolean mFatalReadAt;
private boolean mIsClosed = false;
static TestMediaDataSource fromString(String inpPath, boolean failSize, boolean failRead)
throws IOException {
try (FileInputStream fInp = new FileInputStream(inpPath)) {
int size = (int) new File(inpPath).length();
byte[] data = new byte[size];
fInp.read(data, 0, size);
return new TestMediaDataSource(data, failSize, failRead);
}
}
private TestMediaDataSource(byte[] data, boolean fatalGetSize, boolean fatalReadAt) {
mData = data;
mFatalGetSize = fatalGetSize;
mFatalReadAt = fatalReadAt;
}
@Override
public synchronized int readAt(long srcOffset, byte[] buffer, int dstOffset, int size)
throws IOException {
if (mFatalReadAt) {
throw new IOException("malformed media data source");
}
if (srcOffset >= mData.length) {
return -1;
}
if (srcOffset + size > mData.length) {
size = mData.length - (int) srcOffset;
}
System.arraycopy(mData, (int) srcOffset, buffer, dstOffset, size);
return size;
}
@Override
public synchronized long getSize() throws IOException {
if (mFatalGetSize) {
throw new IOException("malformed media data source");
}
if (ENABLE_LOGS) {
Log.v(LOG_TAG, "getSize: " + mData.length);
}
return mData.length;
}
@Override
public synchronized void close() {
mIsClosed = true;
}
public boolean isClosed() {
return mIsClosed;
}
}
@RunWith(Enclosed.class)
public class ExtractorTest {
private static final String LOG_TAG = ExtractorTest.class.getSimpleName();
private static final boolean ENABLE_LOGS = false;
private static final int MAX_SAMPLE_SIZE = 4 * 1024 * 1024;
private static final String EXT_SEL_KEY = "ext-sel";
static private final List<String> codecListforTypeMp4 =
Arrays.asList(MediaFormat.MIMETYPE_AUDIO_MPEG, MediaFormat.MIMETYPE_AUDIO_AAC,
MediaFormat.MIMETYPE_AUDIO_FLAC, MediaFormat.MIMETYPE_AUDIO_VORBIS,
MediaFormat.MIMETYPE_AUDIO_OPUS, MediaFormat.MIMETYPE_VIDEO_MPEG2,
MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC);
static private final List<String> codecListforTypeWebm =
Arrays.asList(MediaFormat.MIMETYPE_AUDIO_VORBIS, MediaFormat.MIMETYPE_AUDIO_OPUS,
MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9);
static private final List<String> codecListforType3gp =
Arrays.asList(MediaFormat.MIMETYPE_AUDIO_AAC, MediaFormat.MIMETYPE_AUDIO_AMR_NB,
MediaFormat.MIMETYPE_AUDIO_AMR_WB, MediaFormat.MIMETYPE_VIDEO_MPEG4,
MediaFormat.MIMETYPE_VIDEO_H263, MediaFormat.MIMETYPE_VIDEO_AVC);
static private final List<String> codecListforTypeMkv =
Arrays.asList(MediaFormat.MIMETYPE_AUDIO_MPEG, MediaFormat.MIMETYPE_AUDIO_AAC,
MediaFormat.MIMETYPE_AUDIO_FLAC, MediaFormat.MIMETYPE_AUDIO_VORBIS,
MediaFormat.MIMETYPE_AUDIO_OPUS, MediaFormat.MIMETYPE_VIDEO_MPEG2,
MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC,
MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9);
static private final List<String> codecListforTypeOgg =
Arrays.asList(MediaFormat.MIMETYPE_AUDIO_VORBIS, MediaFormat.MIMETYPE_AUDIO_OPUS);
static private final List<String> codecListforTypeTs =
Arrays.asList(MediaFormat.MIMETYPE_AUDIO_AAC, MediaFormat.MIMETYPE_VIDEO_MPEG2,
MediaFormat.MIMETYPE_VIDEO_AVC);
static private final List<String> codecListforTypeRaw =
Arrays.asList(MediaFormat.MIMETYPE_AUDIO_AAC, MediaFormat.MIMETYPE_AUDIO_FLAC,
MediaFormat.MIMETYPE_AUDIO_MPEG, MediaFormat.MIMETYPE_AUDIO_AMR_NB,
MediaFormat.MIMETYPE_AUDIO_AMR_WB, MediaFormat.MIMETYPE_AUDIO_RAW);
// List of codecs that are not required to be supported as per CDD but are tested
static private final List<String> codecListSupp =
Arrays.asList(MediaFormat.MIMETYPE_VIDEO_AV1);
private static String mInpPrefix = WorkDir.getMediaDirString();
private static String extSel;
static {
android.os.Bundle args = InstrumentationRegistry.getArguments();
final String defSel = "mp4;webm;3gp;mkv;ogg;supp";
extSel = (null == args.getString(EXT_SEL_KEY)) ? defSel : args.getString(EXT_SEL_KEY);
}
static private boolean shouldRunTest(String mime) {
boolean result = false;
if ((extSel.contains("mp4") && codecListforTypeMp4.contains(mime)) ||
(extSel.contains("webm") && codecListforTypeWebm.contains(mime)) ||
(extSel.contains("3gp") && codecListforType3gp.contains(mime)) ||
(extSel.contains("mkv") && codecListforTypeMkv.contains(mime)) ||
(extSel.contains("ogg") && codecListforTypeOgg.contains(mime)) ||
(extSel.contains("supp") && codecListSupp.contains(mime)))
result = true;
return result;
}
private static boolean isExtractorOKonEOS(MediaExtractor extractor) {
return extractor.getSampleTrackIndex() < 0 && extractor.getSampleSize() < 0 &&
extractor.getSampleFlags() < 0 && extractor.getSampleTime() < 0;
}
private static boolean isSampleInfoIdentical(MediaCodec.BufferInfo refSample,
MediaCodec.BufferInfo testSample) {
return refSample.flags == testSample.flags && refSample.size == testSample.size &&
refSample.presentationTimeUs == testSample.presentationTimeUs;
}
private static boolean isSampleInfoValidAndIdentical(MediaCodec.BufferInfo refSample,
MediaCodec.BufferInfo testSample) {
return refSample.flags == testSample.flags && refSample.size == testSample.size &&
Math.abs(refSample.presentationTimeUs - testSample.presentationTimeUs) <= 1 &&
refSample.flags >= 0 && refSample.size >= 0 && refSample.presentationTimeUs >= 0;
}
static boolean isCSDIdentical(MediaFormat refFormat, MediaFormat testFormat) {
String mime = refFormat.getString(MediaFormat.KEY_MIME);
for (int i = 0; ; i++) {
String csdKey = "csd-" + i;
boolean refHasCSD = refFormat.containsKey(csdKey);
boolean testHasCSD = testFormat.containsKey(csdKey);
if (refHasCSD != testHasCSD) {
if (ENABLE_LOGS) {
Log.w(LOG_TAG, "error, ref fmt has CSD: " + refHasCSD + " test fmt has CSD: " +
testHasCSD);
}
return false;
}
if (refHasCSD) {
Log.v(LOG_TAG, mime + " has " + csdKey);
ByteBuffer r = refFormat.getByteBuffer(csdKey);
ByteBuffer t = testFormat.getByteBuffer(csdKey);
if (!r.equals(t)) {
if (ENABLE_LOGS) {
Log.w(LOG_TAG, "ref CSD and test CSD buffers are not identical");
}
return false;
}
} else break;
}
return true;
}
private static boolean isFormatSimilar(MediaFormat refFormat, MediaFormat testFormat) {
String refMime = refFormat.getString(MediaFormat.KEY_MIME);
String testMime = testFormat.getString(MediaFormat.KEY_MIME);
if (!refMime.equals(testMime)) return false;
if (!isCSDIdentical(refFormat, testFormat)) return false;
if (refMime.startsWith("audio/")) {
return refFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT) ==
testFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT) &&
refFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE) ==
testFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
} else if (refMime.startsWith("video/")) {
return refFormat.getInteger(MediaFormat.KEY_WIDTH) ==
testFormat.getInteger(MediaFormat.KEY_WIDTH) &&
refFormat.getInteger(MediaFormat.KEY_HEIGHT) ==
testFormat.getInteger(MediaFormat.KEY_HEIGHT);
}
return true;
}
private static boolean isMediaSimilar(MediaExtractor refExtractor, MediaExtractor testExtractor,
String mime, int sampleLimit) {
ByteBuffer refBuffer = ByteBuffer.allocate(MAX_SAMPLE_SIZE);
ByteBuffer testBuffer = ByteBuffer.allocate(MAX_SAMPLE_SIZE);
int noOfTracksMatched = 0;
for (int refTrackID = 0; refTrackID < refExtractor.getTrackCount(); refTrackID++) {
MediaFormat refFormat = refExtractor.getTrackFormat(refTrackID);
String refMime = refFormat.getString(MediaFormat.KEY_MIME);
if (mime != null && !refMime.equals(mime)) {
continue;
}
for (int testTrackID = 0; testTrackID < testExtractor.getTrackCount(); testTrackID++) {
MediaFormat testFormat = testExtractor.getTrackFormat(testTrackID);
if (!isFormatSimilar(refFormat, testFormat)) {
continue;
}
refExtractor.selectTrack(refTrackID);
testExtractor.selectTrack(testTrackID);
MediaCodec.BufferInfo refSampleInfo = new MediaCodec.BufferInfo();
MediaCodec.BufferInfo testSampleInfo = new MediaCodec.BufferInfo();
boolean areTracksIdentical = true;
for (int frameCount = 0; ; frameCount++) {
refSampleInfo.set(0, (int) refExtractor.getSampleSize(),
refExtractor.getSampleTime(), refExtractor.getSampleFlags());
testSampleInfo.set(0, (int) testExtractor.getSampleSize(),
testExtractor.getSampleTime(), testExtractor.getSampleFlags());
if (!isSampleInfoValidAndIdentical(refSampleInfo, testSampleInfo)) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG,
" Mime: " + refMime + " mismatch for sample: " + frameCount);
Log.d(LOG_TAG, " flags exp/got: " +
refSampleInfo.flags + '/' + testSampleInfo.flags);
Log.d(LOG_TAG, " size exp/got: " +
refSampleInfo.size + '/' + testSampleInfo.size);
Log.d(LOG_TAG, " ts exp/got: " + refSampleInfo.presentationTimeUs +
'/' + testSampleInfo.presentationTimeUs);
}
areTracksIdentical = false;
break;
}
int refSz = refExtractor.readSampleData(refBuffer, 0);
if (refSz != refSampleInfo.size) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Mime: " + refMime + " Size exp/got: " +
refSampleInfo.size + '/' + refSz);
}
areTracksIdentical = false;
break;
}
int testSz = testExtractor.readSampleData(testBuffer, 0);
if (testSz != testSampleInfo.size) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Mime: " + refMime + " Size exp/got: " +
testSampleInfo.size + '/' + testSz);
}
areTracksIdentical = false;
break;
}
int trackIndex = refExtractor.getSampleTrackIndex();
if (trackIndex != refTrackID) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Mime: " + refMime +
" TrackID exp/got: " + refTrackID + '/' + trackIndex);
}
areTracksIdentical = false;
break;
}
trackIndex = testExtractor.getSampleTrackIndex();
if (trackIndex != testTrackID) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Mime: " + refMime +
" TrackID exp/got: " + testTrackID + '/' + trackIndex);
}
areTracksIdentical = false;
break;
}
if (!testBuffer.equals(refBuffer)) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Mime: " + refMime + " sample data is not identical");
}
areTracksIdentical = false;
break;
}
boolean haveRefSamples = refExtractor.advance();
boolean haveTestSamples = testExtractor.advance();
if (haveRefSamples != haveTestSamples) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Mime: " + refMime + " Mismatch in sampleCount");
}
areTracksIdentical = false;
break;
}
if (!haveRefSamples && !isExtractorOKonEOS(refExtractor)) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Mime: " + refMime + " calls post advance() are not OK");
}
areTracksIdentical = false;
break;
}
if (!haveTestSamples && !isExtractorOKonEOS(testExtractor)) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Mime: " + refMime + " calls post advance() are not OK");
}
areTracksIdentical = false;
break;
}
if (ENABLE_LOGS) {
Log.v(LOG_TAG, "Mime: " + refMime + " Sample: " + frameCount +
" flags: " + refSampleInfo.flags +
" size: " + refSampleInfo.size +
" ts: " + refSampleInfo.presentationTimeUs);
}
if (!haveRefSamples || frameCount >= sampleLimit) {
break;
}
}
testExtractor.unselectTrack(testTrackID);
refExtractor.unselectTrack(refTrackID);
if (areTracksIdentical) {
noOfTracksMatched++;
break;
}
}
if (mime != null && noOfTracksMatched > 0) break;
}
if (mime == null) {
return noOfTracksMatched == refExtractor.getTrackCount();
} else {
return noOfTracksMatched > 0;
}
}
/**
* Tests setDataSource(...) Api by observing the extractor behavior after its successful
* instantiation using a media stream.
*/
@SmallTest
public static class SetDataSourceTest {
@Rule
public TestName testName = new TestName();
private static final String mInpMedia = "ForBiggerEscapes.mp4";
private static final String mInpMediaUrl =
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4";
private MediaExtractor mRefExtractor;
static {
System.loadLibrary("ctsmediav2extractor_jni");
}
@Before
public void setUp() throws IOException {
mRefExtractor = new MediaExtractor();
mRefExtractor.setDataSource(mInpPrefix + mInpMedia);
}
@After
public void tearDown() {
mRefExtractor.release();
mRefExtractor = null;
}
private static boolean areMetricsIdentical(MediaExtractor refExtractor,
MediaExtractor testExtractor) {
PersistableBundle bundle = refExtractor.getMetrics();
int refNumTracks = bundle.getInt(MediaExtractor.MetricsConstants.TRACKS);
String refFormat = bundle.getString(MediaExtractor.MetricsConstants.FORMAT);
String refMime = bundle.getString(MediaExtractor.MetricsConstants.MIME_TYPE);
bundle = testExtractor.getMetrics();
int testNumTracks = bundle.getInt(MediaExtractor.MetricsConstants.TRACKS);
String testFormat = bundle.getString(MediaExtractor.MetricsConstants.FORMAT);
String testMime = bundle.getString(MediaExtractor.MetricsConstants.MIME_TYPE);
boolean result = testNumTracks == refNumTracks && testFormat.equals(refFormat) &&
testMime.equals(refMime);
if (ENABLE_LOGS) {
Log.d(LOG_TAG, " NumTracks exp/got: " + refNumTracks + '/' + testNumTracks);
Log.d(LOG_TAG, " Format exp/got: " + refFormat + '/' + testFormat);
Log.d(LOG_TAG, " Mime exp/got: " + refMime + '/' + testMime);
}
return result;
}
private static boolean isSeekOk(MediaExtractor refExtractor, MediaExtractor testExtractor) {
final long maxEstDuration = 14000000;
final int MAX_SEEK_POINTS = 7;
final long mSeed = 0x12b9b0a1;
final Random randNum = new Random(mSeed);
MediaCodec.BufferInfo refSampleInfo = new MediaCodec.BufferInfo();
MediaCodec.BufferInfo testSampleInfo = new MediaCodec.BufferInfo();
boolean result = true;
for (int trackID = 0; trackID < refExtractor.getTrackCount() && result; trackID++) {
refExtractor.selectTrack(trackID);
testExtractor.selectTrack(trackID);
for (int i = 0; i < MAX_SEEK_POINTS && result; i++) {
long pts = (long) (randNum.nextDouble() * maxEstDuration);
for (int mode = MediaExtractor.SEEK_TO_PREVIOUS_SYNC;
mode <= MediaExtractor.SEEK_TO_CLOSEST_SYNC; mode++) {
refExtractor.seekTo(pts, mode);
testExtractor.seekTo(pts, mode);
refSampleInfo.set(0, (int) refExtractor.getSampleSize(),
refExtractor.getSampleTime(), refExtractor.getSampleFlags());
testSampleInfo.set(0, (int) testExtractor.getSampleSize(),
testExtractor.getSampleTime(), testExtractor.getSampleFlags());
result = isSampleInfoIdentical(refSampleInfo, testSampleInfo);
int refTrackIdx = refExtractor.getSampleTrackIndex();
int testTrackIdx = testExtractor.getSampleTrackIndex();
result &= (refTrackIdx == testTrackIdx);
if (ENABLE_LOGS) {
Log.d(LOG_TAG, " mode/pts/trackId:" + mode + "/" + pts + "/" + trackID);
Log.d(LOG_TAG, " trackId exp/got: " + refTrackIdx + '/' + testTrackIdx);
Log.d(LOG_TAG, " flags exp/got: " +
refSampleInfo.flags + '/' + testSampleInfo.flags);
Log.d(LOG_TAG, " size exp/got: " +
refSampleInfo.size + '/' + testSampleInfo.size);
Log.d(LOG_TAG, " ts exp/got: " + refSampleInfo.presentationTimeUs +
'/' + testSampleInfo.presentationTimeUs);
}
}
}
refExtractor.unselectTrack(trackID);
testExtractor.unselectTrack(trackID);
}
return result;
}
@Test
public void testAssetFD() throws IOException {
File inpFile = new File(mInpPrefix + mInpMedia);
MediaExtractor testExtractor = new MediaExtractor();
try (ParcelFileDescriptor parcelFD = ParcelFileDescriptor
.open(inpFile, ParcelFileDescriptor.MODE_READ_ONLY);
AssetFileDescriptor afd = new AssetFileDescriptor(parcelFD, 0,
AssetFileDescriptor.UNKNOWN_LENGTH)) {
testExtractor.setDataSource(afd);
}
assertTrue(testExtractor.getCachedDuration() < 0);
if (!isMediaSimilar(mRefExtractor, testExtractor, null, Integer.MAX_VALUE) ||
!areMetricsIdentical(mRefExtractor, testExtractor) ||
!isSeekOk(mRefExtractor, testExtractor)) {
fail("setDataSource failed: " + testName.getMethodName());
}
testExtractor.release();
}
@Test
public void testFileDescriptor() throws IOException {
File inpFile = new File(mInpPrefix + mInpMedia);
MediaExtractor testExtractor = new MediaExtractor();
try (FileInputStream fInp = new FileInputStream(inpFile)) {
testExtractor.setDataSource(fInp.getFD());
}
assertTrue(testExtractor.getCachedDuration() < 0);
if (!isMediaSimilar(mRefExtractor, testExtractor, null, Integer.MAX_VALUE) ||
!areMetricsIdentical(mRefExtractor, testExtractor) ||
!isSeekOk(mRefExtractor, testExtractor)) {
fail("setDataSource failed: " + testName.getMethodName());
}
testExtractor.release();
}
@Test
public void testFileDescriptorLenOffset() throws IOException {
File inpFile = new File(mInpPrefix + mInpMedia);
File outFile = File.createTempFile("temp", ".out");
byte[] garbageAppend = "PrefixGarbage".getBytes();
try (FileInputStream fInp = new FileInputStream(inpFile);
FileOutputStream fOut = new FileOutputStream(outFile)) {
fOut.write(garbageAppend);
byte[] data = new byte[(int) new File(inpFile.toString()).length()];
if (fInp.read(data) == -1) {
fail("Failed to read input file");
}
fOut.write(data);
fOut.write(garbageAppend);
}
MediaExtractor testExtractor = new MediaExtractor();
try (FileInputStream fInp = new FileInputStream(outFile)) {
testExtractor.setDataSource(fInp.getFD(), garbageAppend.length,
inpFile.length());
}
assertTrue(testExtractor.getCachedDuration() < 0);
if (!isMediaSimilar(mRefExtractor, testExtractor, null, Integer.MAX_VALUE) ||
!areMetricsIdentical(mRefExtractor, testExtractor) ||
!isSeekOk(mRefExtractor, testExtractor)) {
fail("setDataSource failed: " + testName.getMethodName());
}
testExtractor.release();
outFile.delete();
}
@Test
public void testMediaDataSource() throws Exception {
TestMediaDataSource dataSource =
TestMediaDataSource.fromString(mInpPrefix + mInpMedia, false, false);
MediaExtractor testExtractor = new MediaExtractor();
testExtractor.setDataSource(dataSource);
assertTrue(testExtractor.getCachedDuration() < 0);
if (!isMediaSimilar(mRefExtractor, testExtractor, null, Integer.MAX_VALUE) ||
!areMetricsIdentical(mRefExtractor, testExtractor) ||
!isSeekOk(mRefExtractor, testExtractor)) {
fail("setDataSource failed: " + testName.getMethodName());
}
testExtractor.release();
assertTrue(dataSource.isClosed());
}
@Test
public void testContextUri() throws IOException {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
String path = "android.resource://android.mediav2.cts/" + R.raw.forbiggerescapes;
MediaExtractor testExtractor = new MediaExtractor();
testExtractor.setDataSource(context, Uri.parse(path), null);
assertTrue(testExtractor.getCachedDuration() < 0);
if (!isMediaSimilar(mRefExtractor, testExtractor, null, Integer.MAX_VALUE) ||
!areMetricsIdentical(mRefExtractor, testExtractor) ||
!isSeekOk(mRefExtractor, testExtractor)) {
fail("setDataSource failed: " + testName.getMethodName());
}
testExtractor.release();
}
@Test
public void testUrlDataSource() throws Exception {
MediaExtractor testExtractor = new MediaExtractor();
testExtractor.setDataSource(mInpMediaUrl, null);
if (!isMediaSimilar(mRefExtractor, testExtractor, null, Integer.MAX_VALUE) ||
!areMetricsIdentical(mRefExtractor, testExtractor) ||
!isSeekOk(mRefExtractor, testExtractor)) {
fail("setDataSource failed: " + testName.getMethodName());
}
testExtractor.selectTrack(0);
for (int idx = 0; ; idx++) {
if ((idx & (idx - 1)) == 0) {
long cachedDuration = testExtractor.getCachedDuration();
if (ENABLE_LOGS) {
Log.v(LOG_TAG, "cachedDuration at frame: " + idx + " is:" + cachedDuration);
}
assertTrue("cached duration should be non-negative", cachedDuration >= 0);
}
if (!testExtractor.advance()) break;
}
assertTrue(testExtractor.hasCacheReachedEndOfStream());
testExtractor.unselectTrack(0);
testExtractor.release();
}
private native boolean nativeTestDataSource(String srcPath, String srcUrl);
@Test
public void testDataSourceNative() {
assertTrue(testName.getMethodName() + " failed ",
nativeTestDataSource(mInpPrefix + mInpMedia, mInpMediaUrl));
}
}
/**
* Encloses extractor functionality tests
*/
@RunWith(Parameterized.class)
public static class FunctionalityTest {
private static final int MAX_SEEK_POINTS = 7;
private static final long mSeed = 0x12b9b0a1;
private final Random mRandNum = new Random(mSeed);
private String[] mSrcFiles;
private String mMime;
static {
System.loadLibrary("ctsmediav2extractor_jni");
}
@Rule
public TestName testName = new TestName();
@Parameterized.Parameters(name = "{index}({0})")
public static Collection<Object[]> input() {
/* TODO(b/157108639) - add missing test files */
return Arrays.asList(new Object[][]{
{MediaFormat.MIMETYPE_VIDEO_MPEG2, new String[]{
"bbb_cif_768kbps_30fps_mpeg2_stereo_48kHz_192kbps_mp3.mp4",
"bbb_cif_768kbps_30fps_mpeg2.mkv",}},
{MediaFormat.MIMETYPE_VIDEO_H263, new String[]{
"bbb_cif_768kbps_30fps_h263.mp4",
"bbb_cif_768kbps_30fps_h263_mono_8kHz_12kbps_amrnb.3gp",}},
{MediaFormat.MIMETYPE_VIDEO_MPEG4, new String[]{
"bbb_cif_768kbps_30fps_mpeg4_stereo_48kHz_192kbps_flac.mp4",
"bbb_cif_768kbps_30fps_mpeg4_mono_16kHz_20kbps_amrwb.3gp",}},
{MediaFormat.MIMETYPE_VIDEO_AVC, new String[]{
"bbb_cif_768kbps_30fps_avc_stereo_48kHz_192kbps_vorbis.mp4",
"bbb_cif_768kbps_30fps_avc_stereo_48kHz_192kbps_aac.mkv",
"bbb_cif_768kbps_30fps_avc_stereo_48kHz_192kbps_aac.3gp",}},
{MediaFormat.MIMETYPE_VIDEO_HEVC, new String[]{
"bbb_cif_768kbps_30fps_hevc_stereo_48kHz_192kbps_opus.mp4",
"bbb_cif_768kbps_30fps_hevc_stereo_48kHz_192kbps_mp3.mkv",}},
{MediaFormat.MIMETYPE_VIDEO_VP8, new String[]{
"bbb_cif_768kbps_30fps_vp8_stereo_48kHz_192kbps_vorbis.webm",
"bbb_cif_768kbps_30fps_vp8_stereo_48kHz_192kbps_vorbis.mkv"}},
{MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{
"bbb_cif_768kbps_30fps_vp9_stereo_48kHz_192kbps_opus.webm",
"bbb_cif_768kbps_30fps_vp9_stereo_48kHz_192kbps_opus.mkv",}},
{MediaFormat.MIMETYPE_VIDEO_AV1, new String[]{
"bbb_cif_768kbps_30fps_av1.mp4",
"bbb_cif_768kbps_30fps_av1.webm",
"bbb_cif_768kbps_30fps_av1.mkv",}},
{MediaFormat.MIMETYPE_AUDIO_VORBIS, new String[]{
"bbb_cif_768kbps_30fps_avc_stereo_48kHz_192kbps_vorbis.mp4",
"bbb_cif_768kbps_30fps_vp8_stereo_48kHz_192kbps_vorbis.mkv",
"bbb_cif_768kbps_30fps_vp8_stereo_48kHz_192kbps_vorbis.webm",
"bbb_stereo_48kHz_192kbps_vorbis.ogg",}},
{MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
"bbb_cif_768kbps_30fps_vp9_stereo_48kHz_192kbps_opus.webm",
"bbb_cif_768kbps_30fps_vp9_stereo_48kHz_192kbps_opus.mkv",
"bbb_cif_768kbps_30fps_hevc_stereo_48kHz_192kbps_opus.mp4",
"bbb_stereo_48kHz_192kbps_opus.ogg",}},
{MediaFormat.MIMETYPE_AUDIO_MPEG, new String[]{
"bbb_stereo_48kHz_192kbps_mp3.mp3",
"bbb_cif_768kbps_30fps_mpeg2_stereo_48kHz_192kbps_mp3.mp4",
"bbb_cif_768kbps_30fps_hevc_stereo_48kHz_192kbps_mp3.mkv",}},
{MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
"bbb_stereo_48kHz_192kbps_aac.mp4",
"bbb_cif_768kbps_30fps_avc_stereo_48kHz_192kbps_aac.3gp",
"bbb_cif_768kbps_30fps_avc_stereo_48kHz_192kbps_aac.mkv",}},
{MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
"bbb_cif_768kbps_30fps_h263_mono_8kHz_12kbps_amrnb.3gp",
"bbb_mono_8kHz_12kbps_amrnb.amr",}},
{MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
"bbb_cif_768kbps_30fps_mpeg4_mono_16kHz_20kbps_amrwb.3gp",
"bbb_mono_16kHz_20kbps_amrwb.amr"}},
{MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{
"bbb_cif_768kbps_30fps_mpeg4_stereo_48kHz_192kbps_flac.mp4",
"bbb_cif_768kbps_30fps_h263_stereo_48kHz_192kbps_flac.mkv",}},
});
}
private native boolean nativeTestExtract(String srcPath, String refPath, String mime);
private native boolean nativeTestSeek(String srcPath, String mime);
private native boolean nativeTestSeekFlakiness(String srcPath, String mime);
private native boolean nativeTestSeekToZero(String srcPath, String mime);
private native boolean nativeTestFileFormat(String srcPath);
public FunctionalityTest(String mime, String[] srcFiles) {
mMime = mime;
mSrcFiles = srcFiles;
}
// content necessary for testing seek are grouped in this class
private class SeekTestParams {
MediaCodec.BufferInfo mExpected;
long mTimeStamp;
int mMode;
SeekTestParams(MediaCodec.BufferInfo expected, long timeStamp, int mode) {
mExpected = expected;
mTimeStamp = timeStamp;
mMode = mode;
}
}
private ArrayList<MediaCodec.BufferInfo> getSeekablePoints(String srcFile, String mime)
throws IOException {
ArrayList<MediaCodec.BufferInfo> bookmarks = null;
if (mime == null) return null;
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(mInpPrefix + srcFile);
for (int trackID = 0; trackID < extractor.getTrackCount(); trackID++) {
MediaFormat format = extractor.getTrackFormat(trackID);
if (!mime.equals(format.getString(MediaFormat.KEY_MIME))) continue;
extractor.selectTrack(trackID);
bookmarks = new ArrayList<>();
do {
int sampleFlags = extractor.getSampleFlags();
if ((sampleFlags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
MediaCodec.BufferInfo sampleInfo = new MediaCodec.BufferInfo();
sampleInfo.set(0, (int) extractor.getSampleSize(),
extractor.getSampleTime(), extractor.getSampleFlags());
bookmarks.add(sampleInfo);
}
} while (extractor.advance());
extractor.unselectTrack(trackID);
break;
}
extractor.release();
return bookmarks;
}
private ArrayList<SeekTestParams> generateSeekTestArgs(String srcFile, String mime,
boolean isRandom) throws IOException {
ArrayList<SeekTestParams> testArgs = new ArrayList<>();
if (mime == null) return null;
if (isRandom) {
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(mInpPrefix + srcFile);
final long maxEstDuration = 4000000;
for (int trackID = 0; trackID < extractor.getTrackCount(); trackID++) {
MediaFormat format = extractor.getTrackFormat(trackID);
if (!mime.equals(format.getString(MediaFormat.KEY_MIME))) continue;
extractor.selectTrack(trackID);
for (int i = 0; i < MAX_SEEK_POINTS; i++) {
long pts = (long) (mRandNum.nextDouble() * maxEstDuration);
for (int mode = MediaExtractor.SEEK_TO_PREVIOUS_SYNC;
mode <= MediaExtractor.SEEK_TO_CLOSEST_SYNC; mode++) {
MediaCodec.BufferInfo currInfo = new MediaCodec.BufferInfo();
extractor.seekTo(pts, mode);
currInfo.set(0, (int) extractor.getSampleSize(),
extractor.getSampleTime(), extractor.getSampleFlags());
testArgs.add(new SeekTestParams(currInfo, pts, mode));
}
}
extractor.unselectTrack(trackID);
break;
}
extractor.release();
} else {
ArrayList<MediaCodec.BufferInfo> bookmarks = getSeekablePoints(srcFile, mime);
if (bookmarks == null) return null;
int size = bookmarks.size();
int[] indices;
if (size > MAX_SEEK_POINTS) {
indices = new int[MAX_SEEK_POINTS];
indices[0] = 0;
indices[MAX_SEEK_POINTS - 1] = size - 1;
for (int i = 1; i < MAX_SEEK_POINTS - 1; i++) {
indices[i] = (int) (mRandNum.nextDouble() * (MAX_SEEK_POINTS - 1) + 1);
}
} else {
indices = new int[size];
for (int i = 0; i < size; i++) indices[i] = i;
}
// closest sync : Seek to the sync sample CLOSEST to the specified time
// previous sync : Seek to a sync sample AT or AFTER the specified time
// next sync : Seek to a sync sample AT or BEFORE the specified time
for (int i : indices) {
MediaCodec.BufferInfo currInfo = bookmarks.get(i);
long pts = currInfo.presentationTimeUs;
testArgs.add(
new SeekTestParams(currInfo, pts, MediaExtractor.SEEK_TO_CLOSEST_SYNC));
testArgs.add(
new SeekTestParams(currInfo, pts, MediaExtractor.SEEK_TO_NEXT_SYNC));
testArgs.add(
new SeekTestParams(currInfo, pts,
MediaExtractor.SEEK_TO_PREVIOUS_SYNC));
if (i > 0) {
MediaCodec.BufferInfo prevInfo = bookmarks.get(i - 1);
long ptsMinus = prevInfo.presentationTimeUs;
ptsMinus = pts - ((pts - ptsMinus) >> 3);
testArgs.add(new SeekTestParams(currInfo, ptsMinus,
MediaExtractor.SEEK_TO_CLOSEST_SYNC));
testArgs.add(new SeekTestParams(currInfo, ptsMinus,
MediaExtractor.SEEK_TO_NEXT_SYNC));
testArgs.add(new SeekTestParams(prevInfo, ptsMinus,
MediaExtractor.SEEK_TO_PREVIOUS_SYNC));
}
if (i < size - 1) {
MediaCodec.BufferInfo nextInfo = bookmarks.get(i + 1);
long ptsPlus = nextInfo.presentationTimeUs;
ptsPlus = pts + ((ptsPlus - pts) >> 3);
testArgs.add(new SeekTestParams(currInfo, ptsPlus,
MediaExtractor.SEEK_TO_CLOSEST_SYNC));
testArgs.add(new SeekTestParams(nextInfo, ptsPlus,
MediaExtractor.SEEK_TO_NEXT_SYNC));
testArgs.add(new SeekTestParams(currInfo, ptsPlus,
MediaExtractor.SEEK_TO_PREVIOUS_SYNC));
}
}
}
return testArgs;
}
int checkSeekPoints(String srcFile, String mime,
ArrayList<SeekTestParams> seekTestArgs) throws IOException {
int errCnt = 0;
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(mInpPrefix + srcFile);
for (int trackID = 0; trackID < extractor.getTrackCount(); trackID++) {
MediaFormat format = extractor.getTrackFormat(trackID);
if (!format.getString(MediaFormat.KEY_MIME).equals(mime)) continue;
extractor.selectTrack(trackID);
MediaCodec.BufferInfo received = new MediaCodec.BufferInfo();
for (SeekTestParams arg : seekTestArgs) {
extractor.seekTo(arg.mTimeStamp, arg.mMode);
received.set(0, (int) extractor.getSampleSize(), extractor.getSampleTime(),
extractor.getSampleFlags());
if (!isSampleInfoIdentical(arg.mExpected, received)) {
errCnt++;
if (ENABLE_LOGS) {
Log.d(LOG_TAG, " flags exp/got: " + arg.mExpected.flags + '/' +
received.flags);
Log.d(LOG_TAG,
" size exp/got: " + arg.mExpected.size + '/' + received.size);
Log.d(LOG_TAG,
" ts exp/got: " + arg.mExpected.presentationTimeUs + '/' +
received.presentationTimeUs);
}
}
}
extractor.unselectTrack(trackID);
break;
}
extractor.release();
return errCnt;
}
/**
* Audio, Video codecs support a variety of file-types/container formats. For example,
* Vorbis supports OGG, MP4, WEBM and MKV. H.263 supports 3GPP, WEBM and MKV. For every
* mime, a list of test vectors are provided one for each container) but underlying
* elementary stream is the same for all. The streams of a mime are extracted and
* compared with each other for similarity.
*/
@LargeTest
@Test
public void testExtract() throws IOException {
assumeTrue(shouldRunTest(mMime));
assertTrue(mSrcFiles.length > 1);
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_VORBIS));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_OPUS));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_MPEG));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC));
MediaExtractor refExtractor = new MediaExtractor();
refExtractor.setDataSource(mInpPrefix + mSrcFiles[0]);
boolean isOk = true;
for (int i = 1; i < mSrcFiles.length && isOk; i++) {
MediaExtractor testExtractor = new MediaExtractor();
testExtractor.setDataSource(mInpPrefix + mSrcFiles[i]);
if (!isMediaSimilar(refExtractor, testExtractor, mMime, Integer.MAX_VALUE)) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "Files: " + mSrcFiles[0] + ", " + mSrcFiles[i] +
" are different from extractor perspective");
}
if (!codecListSupp.contains(mMime)) {
isOk = false;
}
}
testExtractor.release();
}
refExtractor.release();
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
/**
* Tests seek functionality, verifies if we seek to most accurate point for a given
* choice of timestamp and mode.
*/
@LargeTest
@Test
@Ignore("TODO(b/146420831)")
public void testSeek() throws IOException {
assumeTrue(shouldRunTest(mMime));
boolean isOk = true;
for (String srcFile : mSrcFiles) {
ArrayList<SeekTestParams> seekTestArgs =
generateSeekTestArgs(srcFile, mMime, false);
assertTrue("Mime is null.", seekTestArgs != null);
assertTrue("No sync samples found.", !seekTestArgs.isEmpty());
Collections.shuffle(seekTestArgs, mRandNum);
int seekAccErrCnt = checkSeekPoints(srcFile, mMime, seekTestArgs);
if (seekAccErrCnt != 0) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "For " + srcFile + " seek chose inaccurate Sync point in: " +
seekAccErrCnt + "/" + seekTestArgs.size());
}
if (!codecListSupp.contains(mMime)) {
isOk = false;
break;
}
}
}
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
/**
* Tests if we get the same content each time after a call to seekto;
*/
@LargeTest
@Test
public void testSeekFlakiness() throws IOException {
assumeTrue(shouldRunTest(mMime));
boolean isOk = true;
for (String srcFile : mSrcFiles) {
ArrayList<SeekTestParams> seekTestArgs = generateSeekTestArgs(srcFile, mMime, true);
assertTrue("Mime is null.", seekTestArgs != null);
assertTrue("No samples found.", !seekTestArgs.isEmpty());
Collections.shuffle(seekTestArgs, mRandNum);
int flakyErrCnt = checkSeekPoints(srcFile, mMime, seekTestArgs);
if (flakyErrCnt != 0) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG,
"No. of Samples where seek showed flakiness is: " + flakyErrCnt);
}
if (!codecListSupp.contains(mMime)) {
isOk = false;
break;
}
}
}
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
/**
* Test if seekTo(0) yields the same content as if we had just opened the file and started
* reading.
*/
@SmallTest
@Test
public void testSeekToZero() throws IOException {
assumeTrue(shouldRunTest(mMime));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_VORBIS));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_MPEG));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC));
boolean isOk = true;
for (String srcFile : mSrcFiles) {
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(mInpPrefix + srcFile);
MediaCodec.BufferInfo sampleInfoAtZero = new MediaCodec.BufferInfo();
MediaCodec.BufferInfo currInfo = new MediaCodec.BufferInfo();
final long randomSeekPts = 1 << 20;
for (int trackID = 0; trackID < extractor.getTrackCount(); trackID++) {
MediaFormat format = extractor.getTrackFormat(trackID);
if (!mMime.equals(format.getString(MediaFormat.KEY_MIME))) continue;
extractor.selectTrack(trackID);
sampleInfoAtZero.set(0, (int) extractor.getSampleSize(),
extractor.getSampleTime(), extractor.getSampleFlags());
extractor.seekTo(randomSeekPts, MediaExtractor.SEEK_TO_NEXT_SYNC);
extractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
currInfo.set(0, (int) extractor.getSampleSize(),
extractor.getSampleTime(), extractor.getSampleFlags());
if (!isSampleInfoIdentical(sampleInfoAtZero, currInfo)) {
if (!codecListSupp.contains(mMime)) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "seen mismatch seekTo(0, SEEK_TO_CLOSEST_SYNC)");
Log.d(LOG_TAG, " flags exp/got: " + sampleInfoAtZero.flags + '/' +
currInfo.flags);
Log.d(LOG_TAG, " size exp/got: " + sampleInfoAtZero.size + '/' +
currInfo.size);
Log.d(LOG_TAG,
" ts exp/got: " + sampleInfoAtZero.presentationTimeUs +
'/' + currInfo.presentationTimeUs);
}
isOk = false;
break;
}
}
extractor.seekTo(-1L, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
currInfo.set(0, (int) extractor.getSampleSize(),
extractor.getSampleTime(), extractor.getSampleFlags());
if (!isSampleInfoIdentical(sampleInfoAtZero, currInfo)) {
if (!codecListSupp.contains(mMime)) {
if (ENABLE_LOGS) {
Log.d(LOG_TAG, "seen mismatch seekTo(-1, SEEK_TO_CLOSEST_SYNC)");
Log.d(LOG_TAG, " flags exp/got: " + sampleInfoAtZero.flags + '/' +
currInfo.flags);
Log.d(LOG_TAG, " size exp/got: " + sampleInfoAtZero.size + '/' +
currInfo.size);
Log.d(LOG_TAG,
" ts exp/got: " + sampleInfoAtZero.presentationTimeUs +
'/' + currInfo.presentationTimeUs);
}
isOk = false;
break;
}
}
extractor.unselectTrack(trackID);
}
extractor.release();
}
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
@SmallTest
@Test
public void testMetrics() throws IOException {
assumeTrue(shouldRunTest(mMime));
for (String srcFile : mSrcFiles) {
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(mInpPrefix + srcFile);
PersistableBundle bundle = extractor.getMetrics();
int numTracks = bundle.getInt(MediaExtractor.MetricsConstants.TRACKS);
String format = bundle.getString(MediaExtractor.MetricsConstants.FORMAT);
String mime = bundle.getString(MediaExtractor.MetricsConstants.MIME_TYPE);
assertTrue(numTracks == extractor.getTrackCount() && format != null &&
mime != null);
extractor.release();
}
}
@LargeTest
@Test
public void testExtractNative() {
assumeTrue(shouldRunTest(mMime));
assertTrue(mSrcFiles.length > 1);
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_VORBIS));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_OPUS));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_MPEG));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC));
boolean isOk = true;
for (int i = 1; i < mSrcFiles.length; i++) {
if (!nativeTestExtract(mInpPrefix + mSrcFiles[0], mInpPrefix + mSrcFiles[i],
mMime)) {
Log.d(LOG_TAG, "Files: " + mSrcFiles[0] + ", " + mSrcFiles[i] +
" are different from extractor perpsective");
if (!codecListSupp.contains(mMime)) {
isOk = false;
break;
}
}
}
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
@LargeTest
@Test
@Ignore("TODO(b/146420831)")
public void testSeekNative() {
assumeTrue(shouldRunTest(mMime));
boolean isOk = true;
for (String srcFile : mSrcFiles) {
if (!nativeTestSeek(mInpPrefix + srcFile, mMime)) {
if (!codecListSupp.contains(mMime)) {
isOk = false;
break;
}
}
}
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
@LargeTest
@Test
public void testSeekFlakinessNative() {
assumeTrue(shouldRunTest(mMime));
boolean isOk = true;
for (String srcFile : mSrcFiles) {
if (!nativeTestSeekFlakiness(mInpPrefix + srcFile, mMime)) {
if (!codecListSupp.contains(mMime)) {
isOk = false;
break;
}
}
}
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
@SmallTest
@Test
public void testSeekToZeroNative() {
assumeTrue(shouldRunTest(mMime));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_VORBIS));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_MPEG));
assumeTrue("TODO(b/146925481)", !mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC));
boolean isOk = true;
for (String srcFile : mSrcFiles) {
if (!nativeTestSeekToZero(mInpPrefix + srcFile, mMime)) {
if (!codecListSupp.contains(mMime)) {
isOk = false;
break;
}
}
}
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
@SmallTest
@Test
public void testFileFormatNative() {
assumeTrue(shouldRunTest(mMime));
boolean isOk = true;
for (String srcFile : mSrcFiles) {
if (!nativeTestFileFormat(mInpPrefix + srcFile)) {
isOk = false;
break;
}
assertTrue(testName.getMethodName() + " failed for mime: " + mMime, isOk);
}
}
}
}