Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Unified Diff: webrtc/api/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java

Issue 2541823002: Move webrtc/api/androidtests to webrtc/sdk/android/instrumentationtests (Closed)
Patch Set: Make include for webrtc.gni absolute Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/api/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java
diff --git a/webrtc/api/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java b/webrtc/api/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java
deleted file mode 100644
index ee29da85ad9e2d4b02365c6e13043e79f3028a6c..0000000000000000000000000000000000000000
--- a/webrtc/api/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright 2015 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-package org.webrtc;
-
-import android.graphics.SurfaceTexture;
-import android.opengl.GLES20;
-import android.os.SystemClock;
-import android.test.ActivityTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.nio.ByteBuffer;
-import java.util.concurrent.CountDownLatch;
-
-public final class SurfaceTextureHelperTest extends ActivityTestCase {
- /**
- * Mock texture listener with blocking wait functionality.
- */
- public static final class MockTextureListener
- implements SurfaceTextureHelper.OnTextureFrameAvailableListener {
- public int oesTextureId;
- public float[] transformMatrix;
- private boolean hasNewFrame = false;
- // Thread where frames are expected to be received on.
- private final Thread expectedThread;
-
- MockTextureListener() {
- this.expectedThread = null;
- }
-
- MockTextureListener(Thread expectedThread) {
- this.expectedThread = expectedThread;
- }
-
- @Override
- public synchronized void onTextureFrameAvailable(
- int oesTextureId, float[] transformMatrix, long timestampNs) {
- if (expectedThread != null && Thread.currentThread() != expectedThread) {
- throw new IllegalStateException("onTextureFrameAvailable called on wrong thread.");
- }
- this.oesTextureId = oesTextureId;
- this.transformMatrix = transformMatrix;
- hasNewFrame = true;
- notifyAll();
- }
-
- /**
- * Wait indefinitely for a new frame.
- */
- public synchronized void waitForNewFrame() throws InterruptedException {
- while (!hasNewFrame) {
- wait();
- }
- hasNewFrame = false;
- }
-
- /**
- * Wait for a new frame, or until the specified timeout elapses. Returns true if a new frame was
- * received before the timeout.
- */
- public synchronized boolean waitForNewFrame(final long timeoutMs) throws InterruptedException {
- final long startTimeMs = SystemClock.elapsedRealtime();
- long timeRemainingMs = timeoutMs;
- while (!hasNewFrame && timeRemainingMs > 0) {
- wait(timeRemainingMs);
- final long elapsedTimeMs = SystemClock.elapsedRealtime() - startTimeMs;
- timeRemainingMs = timeoutMs - elapsedTimeMs;
- }
- final boolean didReceiveFrame = hasNewFrame;
- hasNewFrame = false;
- return didReceiveFrame;
- }
- }
-
- /** Assert that two integers are close, with difference at most
- * {@code threshold}. */
- public static void assertClose(int threshold, int expected, int actual) {
- if (Math.abs(expected - actual) <= threshold)
- return;
- failNotEquals("Not close enough, threshold " + threshold, expected, actual);
- }
-
- /**
- * Test normal use by receiving three uniform texture frames. Texture frames are returned as early
- * as possible. The texture pixel values are inspected by drawing the texture frame to a pixel
- * buffer and reading it back with glReadPixels().
- */
- @MediumTest
- public static void testThreeConstantColorFrames() throws InterruptedException {
- final int width = 16;
- final int height = 16;
- // Create EGL base with a pixel buffer as display output.
- final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PIXEL_BUFFER);
- eglBase.createPbufferSurface(width, height);
- final GlRectDrawer drawer = new GlRectDrawer();
-
- // Create SurfaceTextureHelper and listener.
- final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
- "SurfaceTextureHelper test" /* threadName */, eglBase.getEglBaseContext());
- final MockTextureListener listener = new MockTextureListener();
- surfaceTextureHelper.startListening(listener);
- surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(width, height);
-
- // Create resources for stubbing an OES texture producer. |eglOesBase| has the SurfaceTexture in
- // |surfaceTextureHelper| as the target EGLSurface.
- final EglBase eglOesBase = EglBase.create(eglBase.getEglBaseContext(), EglBase.CONFIG_PLAIN);
- eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
- assertEquals(eglOesBase.surfaceWidth(), width);
- assertEquals(eglOesBase.surfaceHeight(), height);
-
- final int red[] = new int[] {79, 144, 185};
- final int green[] = new int[] {66, 210, 162};
- final int blue[] = new int[] {161, 117, 158};
- // Draw three frames.
- for (int i = 0; i < 3; ++i) {
- // Draw a constant color frame onto the SurfaceTexture.
- eglOesBase.makeCurrent();
- GLES20.glClearColor(red[i] / 255.0f, green[i] / 255.0f, blue[i] / 255.0f, 1.0f);
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- // swapBuffers() will ultimately trigger onTextureFrameAvailable().
- eglOesBase.swapBuffers();
-
- // Wait for an OES texture to arrive and draw it onto the pixel buffer.
- listener.waitForNewFrame();
- eglBase.makeCurrent();
- drawer.drawOes(
- listener.oesTextureId, listener.transformMatrix, width, height, 0, 0, width, height);
-
- surfaceTextureHelper.returnTextureFrame();
-
- // Download the pixels in the pixel buffer as RGBA. Not all platforms support RGB, e.g.
- // Nexus 9.
- final ByteBuffer rgbaData = ByteBuffer.allocateDirect(width * height * 4);
- GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, rgbaData);
- GlUtil.checkNoGLES2Error("glReadPixels");
-
- // Assert rendered image is expected constant color.
- while (rgbaData.hasRemaining()) {
- assertEquals(rgbaData.get() & 0xFF, red[i]);
- assertEquals(rgbaData.get() & 0xFF, green[i]);
- assertEquals(rgbaData.get() & 0xFF, blue[i]);
- assertEquals(rgbaData.get() & 0xFF, 255);
- }
- }
-
- drawer.release();
- surfaceTextureHelper.dispose();
- eglBase.release();
- }
-
- /**
- * Test disposing the SurfaceTextureHelper while holding a pending texture frame. The pending
- * texture frame should still be valid, and this is tested by drawing the texture frame to a pixel
- * buffer and reading it back with glReadPixels().
- */
- @MediumTest
- public static void testLateReturnFrame() throws InterruptedException {
- final int width = 16;
- final int height = 16;
- // Create EGL base with a pixel buffer as display output.
- final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PIXEL_BUFFER);
- eglBase.createPbufferSurface(width, height);
-
- // Create SurfaceTextureHelper and listener.
- final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
- "SurfaceTextureHelper test" /* threadName */, eglBase.getEglBaseContext());
- final MockTextureListener listener = new MockTextureListener();
- surfaceTextureHelper.startListening(listener);
- surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(width, height);
-
- // Create resources for stubbing an OES texture producer. |eglOesBase| has the SurfaceTexture in
- // |surfaceTextureHelper| as the target EGLSurface.
- final EglBase eglOesBase = EglBase.create(eglBase.getEglBaseContext(), EglBase.CONFIG_PLAIN);
- eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
- assertEquals(eglOesBase.surfaceWidth(), width);
- assertEquals(eglOesBase.surfaceHeight(), height);
-
- final int red = 79;
- final int green = 66;
- final int blue = 161;
- // Draw a constant color frame onto the SurfaceTexture.
- eglOesBase.makeCurrent();
- GLES20.glClearColor(red / 255.0f, green / 255.0f, blue / 255.0f, 1.0f);
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- // swapBuffers() will ultimately trigger onTextureFrameAvailable().
- eglOesBase.swapBuffers();
- eglOesBase.release();
-
- // Wait for OES texture frame.
- listener.waitForNewFrame();
- // Diconnect while holding the frame.
- surfaceTextureHelper.dispose();
-
- // Draw the pending texture frame onto the pixel buffer.
- eglBase.makeCurrent();
- final GlRectDrawer drawer = new GlRectDrawer();
- drawer.drawOes(
- listener.oesTextureId, listener.transformMatrix, width, height, 0, 0, width, height);
- drawer.release();
-
- // Download the pixels in the pixel buffer as RGBA. Not all platforms support RGB, e.g. Nexus 9.
- final ByteBuffer rgbaData = ByteBuffer.allocateDirect(width * height * 4);
- GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, rgbaData);
- GlUtil.checkNoGLES2Error("glReadPixels");
- eglBase.release();
-
- // Assert rendered image is expected constant color.
- while (rgbaData.hasRemaining()) {
- assertEquals(rgbaData.get() & 0xFF, red);
- assertEquals(rgbaData.get() & 0xFF, green);
- assertEquals(rgbaData.get() & 0xFF, blue);
- assertEquals(rgbaData.get() & 0xFF, 255);
- }
- // Late frame return after everything has been disposed and released.
- surfaceTextureHelper.returnTextureFrame();
- }
-
- /**
- * Test disposing the SurfaceTextureHelper, but keep trying to produce more texture frames. No
- * frames should be delivered to the listener.
- */
- @MediumTest
- public static void testDispose() throws InterruptedException {
- // Create SurfaceTextureHelper and listener.
- final SurfaceTextureHelper surfaceTextureHelper =
- SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
- final MockTextureListener listener = new MockTextureListener();
- surfaceTextureHelper.startListening(listener);
- // Create EglBase with the SurfaceTexture as target EGLSurface.
- final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
- eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
- eglBase.makeCurrent();
- // Assert no frame has been received yet.
- assertFalse(listener.waitForNewFrame(1));
- // Draw and wait for one frame.
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- // swapBuffers() will ultimately trigger onTextureFrameAvailable().
- eglBase.swapBuffers();
- listener.waitForNewFrame();
- surfaceTextureHelper.returnTextureFrame();
-
- // Dispose - we should not receive any textures after this.
- surfaceTextureHelper.dispose();
-
- // Draw one frame.
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- eglBase.swapBuffers();
- // swapBuffers() should not trigger onTextureFrameAvailable() because disposed has been called.
- // Assert that no OES texture was delivered.
- assertFalse(listener.waitForNewFrame(500));
-
- eglBase.release();
- }
-
- /**
- * Test disposing the SurfaceTextureHelper immediately after is has been setup to use a
- * shared context. No frames should be delivered to the listener.
- */
- @SmallTest
- public static void testDisposeImmediately() {
- final SurfaceTextureHelper surfaceTextureHelper =
- SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
- surfaceTextureHelper.dispose();
- }
-
- /**
- * Call stopListening(), but keep trying to produce more texture frames. No frames should be
- * delivered to the listener.
- */
- @MediumTest
- public static void testStopListening() throws InterruptedException {
- // Create SurfaceTextureHelper and listener.
- final SurfaceTextureHelper surfaceTextureHelper =
- SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
- final MockTextureListener listener = new MockTextureListener();
- surfaceTextureHelper.startListening(listener);
- // Create EglBase with the SurfaceTexture as target EGLSurface.
- final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
- eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
- eglBase.makeCurrent();
- // Assert no frame has been received yet.
- assertFalse(listener.waitForNewFrame(1));
- // Draw and wait for one frame.
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- // swapBuffers() will ultimately trigger onTextureFrameAvailable().
- eglBase.swapBuffers();
- listener.waitForNewFrame();
- surfaceTextureHelper.returnTextureFrame();
-
- // Stop listening - we should not receive any textures after this.
- surfaceTextureHelper.stopListening();
-
- // Draw one frame.
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- eglBase.swapBuffers();
- // swapBuffers() should not trigger onTextureFrameAvailable() because disposed has been called.
- // Assert that no OES texture was delivered.
- assertFalse(listener.waitForNewFrame(500));
-
- surfaceTextureHelper.dispose();
- eglBase.release();
- }
-
- /**
- * Test stopListening() immediately after the SurfaceTextureHelper has been setup.
- */
- @SmallTest
- public static void testStopListeningImmediately() throws InterruptedException {
- final SurfaceTextureHelper surfaceTextureHelper =
- SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
- final MockTextureListener listener = new MockTextureListener();
- surfaceTextureHelper.startListening(listener);
- surfaceTextureHelper.stopListening();
- surfaceTextureHelper.dispose();
- }
-
- /**
- * Test stopListening() immediately after the SurfaceTextureHelper has been setup on the handler
- * thread.
- */
- @SmallTest
- public static void testStopListeningImmediatelyOnHandlerThread() throws InterruptedException {
- final SurfaceTextureHelper surfaceTextureHelper =
- SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
- final MockTextureListener listener = new MockTextureListener();
-
- final CountDownLatch stopListeningBarrier = new CountDownLatch(1);
- final CountDownLatch stopListeningBarrierDone = new CountDownLatch(1);
- // Start by posting to the handler thread to keep it occupied.
- surfaceTextureHelper.getHandler().post(new Runnable() {
- @Override
- public void run() {
- ThreadUtils.awaitUninterruptibly(stopListeningBarrier);
- surfaceTextureHelper.stopListening();
- stopListeningBarrierDone.countDown();
- }
- });
-
- // startListening() is asynchronous and will post to the occupied handler thread.
- surfaceTextureHelper.startListening(listener);
- // Wait for stopListening() to be called on the handler thread.
- stopListeningBarrier.countDown();
- stopListeningBarrierDone.await();
- // Wait until handler thread is idle to try to catch late startListening() call.
- final CountDownLatch barrier = new CountDownLatch(1);
- surfaceTextureHelper.getHandler().post(new Runnable() {
- @Override
- public void run() {
- barrier.countDown();
- }
- });
- ThreadUtils.awaitUninterruptibly(barrier);
- // Previous startListening() call should never have taken place and it should be ok to call it
- // again.
- surfaceTextureHelper.startListening(listener);
-
- surfaceTextureHelper.dispose();
- }
-
- /**
- * Test calling startListening() with a new listener after stopListening() has been called.
- */
- @MediumTest
- public static void testRestartListeningWithNewListener() throws InterruptedException {
- // Create SurfaceTextureHelper and listener.
- final SurfaceTextureHelper surfaceTextureHelper =
- SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
- final MockTextureListener listener1 = new MockTextureListener();
- surfaceTextureHelper.startListening(listener1);
- // Create EglBase with the SurfaceTexture as target EGLSurface.
- final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
- eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
- eglBase.makeCurrent();
- // Assert no frame has been received yet.
- assertFalse(listener1.waitForNewFrame(1));
- // Draw and wait for one frame.
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- // swapBuffers() will ultimately trigger onTextureFrameAvailable().
- eglBase.swapBuffers();
- listener1.waitForNewFrame();
- surfaceTextureHelper.returnTextureFrame();
-
- // Stop listening - |listener1| should not receive any textures after this.
- surfaceTextureHelper.stopListening();
-
- // Connect different listener.
- final MockTextureListener listener2 = new MockTextureListener();
- surfaceTextureHelper.startListening(listener2);
- // Assert no frame has been received yet.
- assertFalse(listener2.waitForNewFrame(1));
-
- // Draw one frame.
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- eglBase.swapBuffers();
-
- // Check that |listener2| received the frame, and not |listener1|.
- listener2.waitForNewFrame();
- assertFalse(listener1.waitForNewFrame(1));
-
- surfaceTextureHelper.returnTextureFrame();
-
- surfaceTextureHelper.dispose();
- eglBase.release();
- }
-
- @MediumTest
- public static void testTexturetoYUV() throws InterruptedException {
- final int width = 16;
- final int height = 16;
-
- final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
-
- // Create SurfaceTextureHelper and listener.
- final SurfaceTextureHelper surfaceTextureHelper = SurfaceTextureHelper.create(
- "SurfaceTextureHelper test" /* threadName */, eglBase.getEglBaseContext());
- final MockTextureListener listener = new MockTextureListener();
- surfaceTextureHelper.startListening(listener);
- surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(width, height);
-
- // Create resources for stubbing an OES texture producer. |eglBase| has the SurfaceTexture in
- // |surfaceTextureHelper| as the target EGLSurface.
-
- eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
- assertEquals(eglBase.surfaceWidth(), width);
- assertEquals(eglBase.surfaceHeight(), height);
-
- final int red[] = new int[] {79, 144, 185};
- final int green[] = new int[] {66, 210, 162};
- final int blue[] = new int[] {161, 117, 158};
-
- final int ref_y[] = new int[] {81, 180, 168};
- final int ref_u[] = new int[] {173, 93, 122};
- final int ref_v[] = new int[] {127, 103, 140};
-
- // Draw three frames.
- for (int i = 0; i < 3; ++i) {
- // Draw a constant color frame onto the SurfaceTexture.
- eglBase.makeCurrent();
- GLES20.glClearColor(red[i] / 255.0f, green[i] / 255.0f, blue[i] / 255.0f, 1.0f);
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
- // swapBuffers() will ultimately trigger onTextureFrameAvailable().
- eglBase.swapBuffers();
-
- // Wait for an OES texture to arrive.
- listener.waitForNewFrame();
-
- // Memory layout: Lines are 16 bytes. First 16 lines are
- // the Y data. These are followed by 8 lines with 8 bytes of U
- // data on the left and 8 bytes of V data on the right.
- //
- // Offset
- // 0 YYYYYYYY YYYYYYYY
- // 16 YYYYYYYY YYYYYYYY
- // ...
- // 240 YYYYYYYY YYYYYYYY
- // 256 UUUUUUUU VVVVVVVV
- // 272 UUUUUUUU VVVVVVVV
- // ...
- // 368 UUUUUUUU VVVVVVVV
- // 384 buffer end
- ByteBuffer buffer = ByteBuffer.allocateDirect(width * height * 3 / 2);
- surfaceTextureHelper.textureToYUV(
- buffer, width, height, width, listener.oesTextureId, listener.transformMatrix);
-
- surfaceTextureHelper.returnTextureFrame();
-
- // Allow off-by-one differences due to different rounding.
- while (buffer.position() < width * height) {
- assertClose(1, buffer.get() & 0xff, ref_y[i]);
- }
- while (buffer.hasRemaining()) {
- if (buffer.position() % width < width / 2)
- assertClose(1, buffer.get() & 0xff, ref_u[i]);
- else
- assertClose(1, buffer.get() & 0xff, ref_v[i]);
- }
- }
-
- surfaceTextureHelper.dispose();
- eglBase.release();
- }
-}

Powered by Google App Engine
This is Rietveld 408576698