cts: add test for persistent input surface
Change-Id: I0235f9dc32076ca4e851fa619390bb2c601f2385
diff --git a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
index b6c94c14..5152d98 100644
--- a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
@@ -209,15 +209,32 @@
*/
public void testEncodeDecodeVideoFromSurfaceToSurfaceQCIF() throws Throwable {
setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this);
+ SurfaceToSurfaceWrapper.runTest(this, false);
}
public void testEncodeDecodeVideoFromSurfaceToSurfaceQVGA() throws Throwable {
setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this);
+ SurfaceToSurfaceWrapper.runTest(this, false);
}
public void testEncodeDecodeVideoFromSurfaceToSurface720p() throws Throwable {
setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this);
+ SurfaceToSurfaceWrapper.runTest(this, false);
+ }
+
+ /**
+ * Tests streaming of AVC video through the encoder and decoder. Data is provided through
+ * a PersistentSurface and decoded onto a Surface. The output is checked for validity.
+ */
+ public void testEncodeDecodeVideoFromPersistentSurfaceToSurfaceQCIF() throws Throwable {
+ setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
+ SurfaceToSurfaceWrapper.runTest(this, true);
+ }
+ public void testEncodeDecodeVideoFromPersistentSurfaceToSurfaceQVGA() throws Throwable {
+ setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
+ SurfaceToSurfaceWrapper.runTest(this, true);
+ }
+ public void testEncodeDecodeVideoFromPersistentSurfaceToSurface720p() throws Throwable {
+ setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
+ SurfaceToSurfaceWrapper.runTest(this, true);
}
/**
@@ -226,40 +243,77 @@
*/
public void testVP8EncodeDecodeVideoFromSurfaceToSurfaceQCIF() throws Throwable {
setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this);
+ SurfaceToSurfaceWrapper.runTest(this, false);
}
public void testVP8EncodeDecodeVideoFromSurfaceToSurfaceQVGA() throws Throwable {
setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this);
+ SurfaceToSurfaceWrapper.runTest(this, false);
}
public void testVP8EncodeDecodeVideoFromSurfaceToSurface720p() throws Throwable {
setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this);
+ SurfaceToSurfaceWrapper.runTest(this, false);
+ }
+
+ /**
+ * Tests streaming of VP8 video through the encoder and decoder. Data is provided through
+ * a PersistentSurface and decoded onto a Surface. The output is checked for validity.
+ */
+ public void testVP8EncodeDecodeVideoFromPersistentSurfaceToSurfaceQCIF() throws Throwable {
+ setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
+ SurfaceToSurfaceWrapper.runTest(this, true);
+ }
+ public void testVP8EncodeDecodeVideoFromPersistentSurfaceToSurfaceQVGA() throws Throwable {
+ setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
+ SurfaceToSurfaceWrapper.runTest(this, true);
+ }
+ public void testVP8EncodeDecodeVideoFromPersistentSurfaceToSurface720p() throws Throwable {
+ setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
+ SurfaceToSurfaceWrapper.runTest(this, true);
}
/** Wraps testEncodeDecodeVideoFromSurfaceToSurface() */
private static class SurfaceToSurfaceWrapper implements Runnable {
private Throwable mThrowable;
private EncodeDecodeTest mTest;
+ private boolean mUsePersistentInput;
- private SurfaceToSurfaceWrapper(EncodeDecodeTest test) {
+ private SurfaceToSurfaceWrapper(EncodeDecodeTest test, boolean persistent) {
mTest = test;
+ mUsePersistentInput = persistent;
}
@Override
public void run() {
+ InputSurface inputSurface = null;
try {
- mTest.encodeDecodeVideoFromSurfaceToSurface();
+ if (!mUsePersistentInput) {
+ mTest.encodeDecodeVideoFromSurfaceToSurface(null);
+ } else {
+ Log.d(TAG, "creating persistent surface");
+ inputSurface = new InputSurface(
+ MediaCodec.createPersistentInputSurface());
+
+ for (int i = 0; i < 3; i++) {
+ Log.d(TAG, "test persistent surface - round " + i);
+ mTest.encodeDecodeVideoFromSurfaceToSurface(inputSurface);
+ }
+ }
} catch (Throwable th) {
mThrowable = th;
+ } finally {
+ if (inputSurface != null) {
+ inputSurface.release();
+ }
}
}
/**
* Entry point.
*/
- public static void runTest(EncodeDecodeTest obj) throws Throwable {
- SurfaceToSurfaceWrapper wrapper = new SurfaceToSurfaceWrapper(obj);
+ public static void runTest(EncodeDecodeTest obj, boolean persisent)
+ throws Throwable {
+ SurfaceToSurfaceWrapper wrapper =
+ new SurfaceToSurfaceWrapper(obj, persisent);
Thread th = new Thread(wrapper, "codec test");
th.start();
th.join();
@@ -357,10 +411,10 @@
* We encode several frames of a video test pattern using MediaCodec, then decode the
* output with MediaCodec and do some simple checks.
*/
- private void encodeDecodeVideoFromSurfaceToSurface() throws Exception {
+ private void encodeDecodeVideoFromSurfaceToSurface(InputSurface inSurf) throws Exception {
MediaCodec encoder = null;
MediaCodec decoder = null;
- InputSurface inputSurface = null;
+ InputSurface inputSurface = inSurf;
OutputSurface outputSurface = null;
mLargestColorDelta = -1;
@@ -402,13 +456,19 @@
// our desired properties. Request a Surface to use for input.
encoder = MediaCodec.createByCodecName(codec);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
- inputSurface = new InputSurface(encoder.createInputSurface());
+ if (inSurf != null) {
+ Log.d(TAG, "using persistent surface");
+ encoder.usePersistentInputSurface(inputSurface.getSurface());
+ inputSurface.updateSize(mWidth, mHeight);
+ } else {
+ inputSurface = new InputSurface(encoder.createInputSurface());
+ }
encoder.start();
doEncodeDecodeVideoFromSurfaceToSurface(encoder, inputSurface, decoder, outputSurface);
} finally {
if (VERBOSE) Log.d(TAG, "releasing codecs");
- if (inputSurface != null) {
+ if (inSurf == null && inputSurface != null) {
inputSurface.release();
}
if (outputSurface != null) {
diff --git a/tests/tests/media/src/android/media/cts/InputSurface.java b/tests/tests/media/src/android/media/cts/InputSurface.java
index 157ed88..37ca423 100644
--- a/tests/tests/media/src/android/media/cts/InputSurface.java
+++ b/tests/tests/media/src/android/media/cts/InputSurface.java
@@ -41,8 +41,11 @@
private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
+ private EGLConfig[] mConfigs = new EGLConfig[1];
private Surface mSurface;
+ private int mWidth;
+ private int mHeight;
/**
* Creates an InputSurface from a Surface.
@@ -80,9 +83,8 @@
EGL_RECORDABLE_ANDROID, 1,
EGL14.EGL_NONE
};
- EGLConfig[] configs = new EGLConfig[1];
int[] numConfigs = new int[1];
- if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
+ if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, mConfigs, 0, mConfigs.length,
numConfigs, 0)) {
throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
}
@@ -92,7 +94,7 @@
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
EGL14.EGL_NONE
};
- mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
+ mEGLContext = EGL14.eglCreateContext(mEGLDisplay, mConfigs[0], EGL14.EGL_NO_CONTEXT,
attrib_list, 0);
checkEglError("eglCreateContext");
if (mEGLContext == null) {
@@ -100,17 +102,40 @@
}
// Create a window surface, and attach it to the Surface we received.
+ createEGLSurface();
+
+ mWidth = getWidth();
+ mHeight = getHeight();
+ }
+
+ public void updateSize(int width, int height) {
+ if (width != mWidth || height != mHeight) {
+ Log.d(TAG, "re-create EGLSurface");
+ releaseEGLSurface();
+ createEGLSurface();
+ mWidth = getWidth();
+ mHeight = getHeight();
+ }
+ }
+
+ private void createEGLSurface() {
+ //EGLConfig[] configs = new EGLConfig[1];
int[] surfaceAttribs = {
EGL14.EGL_NONE
};
- mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
+ mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mConfigs[0], mSurface,
surfaceAttribs, 0);
checkEglError("eglCreateWindowSurface");
if (mEGLSurface == null) {
throw new RuntimeException("surface was null");
}
}
-
+ private void releaseEGLSurface() {
+ if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
+ EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
+ mEGLSurface = EGL14.EGL_NO_SURFACE;
+ }
+ }
/**
* Discard all resources held by this class, notably the EGL context. Also releases the
* Surface that was passed to our constructor.