blob: 7ec3e18dfcc66e4f8d5fa3e72e1b02d7731be280 [file] [log] [blame]
/*
* Copyright (C) 2014 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.media.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.content.res.AssetFileDescriptor;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaPlayer;
import android.media.cts.TestUtils.Monitor;
import android.net.Uri;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresDevice;
import android.util.Log;
import android.view.Surface;
import android.webkit.cts.CtsTestServer;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.ApiLevelUtil;
import com.android.compatibility.common.util.MediaUtils;
import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.impl.io.SocketOutputBuffer;
import org.apache.http.io.SessionOutputBuffer;
import org.apache.http.params.HttpParams;
import org.apache.http.util.CharArrayBuffer;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@SmallTest
@RequiresDevice
@AppModeFull(reason = "TODO: evaluate and port to instant")
@RunWith(AndroidJUnit4.class)
public class NativeDecoderTest extends MediaPlayerTestBase {
private static final String TAG = "DecoderTest";
private static final boolean sIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
static final String mInpPrefix = WorkDir.getMediaDirString();
short[] mMasterBuffer;
static {
// Load jni on initialization.
Log.i("@@@", "before loadlibrary");
System.loadLibrary("ctsmediacodec_jni");
Log.i("@@@", "after loadlibrary");
}
@Before
@Override
public void setUp() throws Throwable {
super.setUp();
}
@After
@Override
public void tearDown() {
super.tearDown();
}
protected static AssetFileDescriptor getAssetFileDescriptorFor(final String res)
throws FileNotFoundException {
Preconditions.assertTestFileExists(mInpPrefix + res);
File inpFile = new File(mInpPrefix + res);
ParcelFileDescriptor parcelFD =
ParcelFileDescriptor.open(inpFile, ParcelFileDescriptor.MODE_READ_ONLY);
return new AssetFileDescriptor(parcelFD, 0, parcelFD.getStatSize());
}
@Presubmit
@Test
public void testFormat() throws Exception {
assertTrue("media format fail, see log for details", testFormatNative());
}
private static native boolean testFormatNative();
@Presubmit
@Test
public void testPssh() throws Exception {
testPssh("psshtest.mp4");
}
private void testPssh(final String res) throws Exception {
AssetFileDescriptor fd = getAssetFileDescriptorFor(res);
MediaExtractor ex = new MediaExtractor();
ex.setDataSource(fd.getParcelFileDescriptor().getFileDescriptor(),
fd.getStartOffset(), fd.getLength());
testPssh(ex);
ex.release();
boolean ret = testPsshNative(
fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength());
assertTrue("native pssh error", ret);
}
private static void testPssh(MediaExtractor ex) {
Map<UUID, byte[]> map = ex.getPsshInfo();
Set<UUID> keys = map.keySet();
for (UUID uuid: keys) {
Log.i("@@@", "uuid: " + uuid + ", data size " +
map.get(uuid).length);
}
}
private static native boolean testPsshNative(int fd, long offset, long size);
@Test
public void testCryptoInfo() throws Exception {
assertTrue("native cryptoinfo failed, see log for details", testCryptoInfoNative());
}
private static native boolean testCryptoInfoNative();
@Presubmit
@Test
public void testMediaFormat() throws Exception {
assertTrue("native mediaformat failed, see log for details", testMediaFormatNative());
}
private static native boolean testMediaFormatNative();
@Presubmit
@Test
public void testAMediaDataSourceClose() throws Throwable {
final CtsTestServer slowServer = new SlowCtsTestServer();
final String url = slowServer.getAssetUrl("noiseandchirps.ogg");
final long ds = createAMediaDataSource(url);
final long ex = createAMediaExtractor();
try {
setAMediaExtractorDataSourceAndFailIfAnr(ex, ds);
} finally {
slowServer.shutdown();
deleteAMediaExtractor(ex);
deleteAMediaDataSource(ds);
}
}
private void setAMediaExtractorDataSourceAndFailIfAnr(final long ex, final long ds)
throws Throwable {
final Monitor setAMediaExtractorDataSourceDone = new Monitor();
final int HEAD_START_MILLIS = 1000;
final int ANR_TIMEOUT_MILLIS = 2500;
final int JOIN_TIMEOUT_MILLIS = 1500;
Thread setAMediaExtractorDataSourceThread = new Thread() {
public void run() {
setAMediaExtractorDataSource(ex, ds);
setAMediaExtractorDataSourceDone.signal();
}
};
try {
setAMediaExtractorDataSourceThread.start();
Thread.sleep(HEAD_START_MILLIS);
closeAMediaDataSource(ds);
boolean closed = setAMediaExtractorDataSourceDone.waitForSignal(ANR_TIMEOUT_MILLIS);
assertTrue("close took longer than " + ANR_TIMEOUT_MILLIS, closed);
} finally {
setAMediaExtractorDataSourceThread.join(JOIN_TIMEOUT_MILLIS);
}
}
private class SlowCtsTestServer extends CtsTestServer {
private static final int SERVER_DELAY_MILLIS = 5000;
private final CountDownLatch mDisconnected = new CountDownLatch(1);
SlowCtsTestServer() throws Exception {
super(mContext);
}
@Override
protected DefaultHttpServerConnection createHttpServerConnection() {
return new SlowHttpServerConnection(mDisconnected, SERVER_DELAY_MILLIS);
}
@Override
public void shutdown() {
mDisconnected.countDown();
super.shutdown();
}
}
private static class SlowHttpServerConnection extends DefaultHttpServerConnection {
private final CountDownLatch mDisconnected;
private final int mDelayMillis;
public SlowHttpServerConnection(CountDownLatch disconnected, int delayMillis) {
mDisconnected = disconnected;
mDelayMillis = delayMillis;
}
@Override
protected SessionOutputBuffer createHttpDataTransmitter(
Socket socket, int buffersize, HttpParams params) throws IOException {
return createSessionOutputBuffer(socket, buffersize, params);
}
SessionOutputBuffer createSessionOutputBuffer(
Socket socket, int buffersize, HttpParams params) throws IOException {
return new SocketOutputBuffer(socket, buffersize, params) {
@Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
while (len-- > 0) {
write(b[off++]);
}
}
@Override
public void writeLine(String s) throws IOException {
delay();
super.writeLine(s);
}
@Override
public void writeLine(CharArrayBuffer buffer) throws IOException {
delay();
super.writeLine(buffer);
}
@Override
public void write(int b) throws IOException {
delay();
super.write(b);
}
private void delay() throws IOException {
try {
mDisconnected.await(mDelayMillis, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// Ignored
}
}
};
}
}
private static native long createAMediaExtractor();
private static native long createAMediaDataSource(String url);
private static native int setAMediaExtractorDataSource(long ex, long ds);
private static native void closeAMediaDataSource(long ds);
private static native void deleteAMediaExtractor(long ex);
private static native void deleteAMediaDataSource(long ds);
}