Android: Update tests to use new SurfaceTextureHelper interface
Bug: webrtc:9412 Change-Id: I17d2f2cb4e1271d07958c6b7f2db47960e4b39ee Reviewed-on: https://webrtc-review.googlesource.com/87260 Reviewed-by: Sami Kalliomäki <sakal@webrtc.org> Commit-Queue: Magnus Jedvert <magjed@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23877}
This commit is contained in:

committed by
Commit Bot

parent
5e898d612e
commit
bf7463b88f
@ -293,14 +293,15 @@ public class GlRectDrawerTest {
|
||||
|
||||
// Draw the frame and block until an OES texture is delivered.
|
||||
oesProducer.draw(rgbPlane);
|
||||
listener.waitForNewFrame();
|
||||
final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
|
||||
|
||||
// Real test starts here.
|
||||
// Draw the OES texture on the pixel buffer.
|
||||
eglBase.makeCurrent();
|
||||
final GlRectDrawer drawer = new GlRectDrawer();
|
||||
drawer.drawOes(listener.oesTextureId, listener.transformMatrix, WIDTH, HEIGHT,
|
||||
0 /* viewportX */, 0 /* viewportY */, WIDTH, HEIGHT);
|
||||
drawer.drawOes(textureBuffer.getTextureId(),
|
||||
RendererCommon.convertMatrixFromAndroidGraphicsMatrix(textureBuffer.getTransformMatrix()),
|
||||
WIDTH, HEIGHT, 0 /* viewportX */, 0 /* viewportY */, WIDTH, HEIGHT);
|
||||
|
||||
// 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);
|
||||
@ -311,7 +312,7 @@ public class GlRectDrawerTest {
|
||||
assertByteBufferEquals(WIDTH, HEIGHT, stripAlphaChannel(rgbaData), rgbPlane);
|
||||
|
||||
drawer.release();
|
||||
surfaceTextureHelper.returnTextureFrame();
|
||||
textureBuffer.release();
|
||||
oesProducer.release();
|
||||
surfaceTextureHelper.dispose();
|
||||
eglBase.release();
|
||||
|
@ -12,6 +12,7 @@ package org.webrtc;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import android.graphics.SurfaceTexture;
|
||||
@ -32,11 +33,9 @@ public class SurfaceTextureHelperTest {
|
||||
/**
|
||||
* 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;
|
||||
public static final class MockTextureListener implements VideoSink {
|
||||
private final Object lock = new Object();
|
||||
private @Nullable VideoFrame.TextureBuffer textureBuffer;
|
||||
// Thread where frames are expected to be received on.
|
||||
private final @Nullable Thread expectedThread;
|
||||
|
||||
@ -49,48 +48,43 @@ public class SurfaceTextureHelperTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
|
||||
@SuppressWarnings("NoSynchronizedMethodCheck")
|
||||
public synchronized void onTextureFrameAvailable(
|
||||
int oesTextureId, float[] transformMatrix, long timestampNs) {
|
||||
public void onFrame(VideoFrame frame) {
|
||||
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.
|
||||
*/
|
||||
// TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
|
||||
@SuppressWarnings("NoSynchronizedMethodCheck")
|
||||
public synchronized void waitForNewFrame() throws InterruptedException {
|
||||
while (!hasNewFrame) {
|
||||
wait();
|
||||
synchronized (lock) {
|
||||
this.textureBuffer = (VideoFrame.TextureBuffer) frame.getBuffer();
|
||||
textureBuffer.retain();
|
||||
lock.notifyAll();
|
||||
}
|
||||
hasNewFrame = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a new frame, or until the specified timeout elapses. Returns true if a new frame was
|
||||
* received before the timeout.
|
||||
*/
|
||||
// TODO(bugs.webrtc.org/8491): Remove NoSynchronizedMethodCheck suppression.
|
||||
@SuppressWarnings("NoSynchronizedMethodCheck")
|
||||
public synchronized boolean waitForNewFrame(final long timeoutMs) throws InterruptedException {
|
||||
/** Wait indefinitely for a new textureBuffer. */
|
||||
public VideoFrame.TextureBuffer waitForTextureBuffer() throws InterruptedException {
|
||||
synchronized (lock) {
|
||||
while (true) {
|
||||
final VideoFrame.TextureBuffer textureBufferToReturn = textureBuffer;
|
||||
if (textureBufferToReturn != null) {
|
||||
textureBuffer = null;
|
||||
return textureBufferToReturn;
|
||||
}
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Make sure we get no frame in the specified time period. */
|
||||
public void assertNoFrameIsDelivered(final long waitPeriodMs) 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;
|
||||
long timeRemainingMs = waitPeriodMs;
|
||||
synchronized (lock) {
|
||||
while (textureBuffer == null && timeRemainingMs > 0) {
|
||||
lock.wait(timeRemainingMs);
|
||||
final long elapsedTimeMs = SystemClock.elapsedRealtime() - startTimeMs;
|
||||
timeRemainingMs = waitPeriodMs - elapsedTimeMs;
|
||||
}
|
||||
assertTrue(textureBuffer == null);
|
||||
}
|
||||
final boolean didReceiveFrame = hasNewFrame;
|
||||
hasNewFrame = false;
|
||||
return didReceiveFrame;
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,12 +145,12 @@ public class SurfaceTextureHelperTest {
|
||||
eglOesBase.swapBuffers();
|
||||
|
||||
// Wait for an OES texture to arrive and draw it onto the pixel buffer.
|
||||
listener.waitForNewFrame();
|
||||
final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
|
||||
eglBase.makeCurrent();
|
||||
drawer.drawOes(
|
||||
listener.oesTextureId, listener.transformMatrix, width, height, 0, 0, width, height);
|
||||
|
||||
surfaceTextureHelper.returnTextureFrame();
|
||||
drawer.drawOes(textureBuffer.getTextureId(),
|
||||
RendererCommon.convertMatrixFromAndroidGraphicsMatrix(textureBuffer.getTransformMatrix()),
|
||||
width, height, 0, 0, width, height);
|
||||
textureBuffer.release();
|
||||
|
||||
// Download the pixels in the pixel buffer as RGBA. Not all platforms support RGB, e.g.
|
||||
// Nexus 9.
|
||||
@ -218,15 +212,16 @@ public class SurfaceTextureHelperTest {
|
||||
eglOesBase.release();
|
||||
|
||||
// Wait for OES texture frame.
|
||||
listener.waitForNewFrame();
|
||||
final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
|
||||
// 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.drawOes(textureBuffer.getTextureId(),
|
||||
RendererCommon.convertMatrixFromAndroidGraphicsMatrix(textureBuffer.getTransformMatrix()),
|
||||
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.
|
||||
@ -243,7 +238,7 @@ public class SurfaceTextureHelperTest {
|
||||
assertEquals(rgbaData.get() & 0xFF, 255);
|
||||
}
|
||||
// Late frame return after everything has been disposed and released.
|
||||
surfaceTextureHelper.returnTextureFrame();
|
||||
textureBuffer.release();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,16 +255,16 @@ public class SurfaceTextureHelperTest {
|
||||
surfaceTextureHelper.startListening(listener);
|
||||
// Create EglBase with the SurfaceTexture as target EGLSurface.
|
||||
final EglBase eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
|
||||
surfaceTextureHelper.setTextureSize(/* textureWidth= */ 32, /* textureHeight= */ 32);
|
||||
eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
|
||||
eglBase.makeCurrent();
|
||||
// Assert no frame has been received yet.
|
||||
assertFalse(listener.waitForNewFrame(1));
|
||||
listener.assertNoFrameIsDelivered(/* waitPeriodMs= */ 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();
|
||||
listener.waitForTextureBuffer().release();
|
||||
|
||||
// Dispose - we should not receive any textures after this.
|
||||
surfaceTextureHelper.dispose();
|
||||
@ -279,7 +274,7 @@ public class SurfaceTextureHelperTest {
|
||||
eglBase.swapBuffers();
|
||||
// swapBuffers() should not trigger onTextureFrameAvailable() because disposed has been called.
|
||||
// Assert that no OES texture was delivered.
|
||||
assertFalse(listener.waitForNewFrame(500));
|
||||
listener.assertNoFrameIsDelivered(/* waitPeriodMs= */ 500);
|
||||
|
||||
eglBase.release();
|
||||
}
|
||||
@ -306,6 +301,7 @@ public class SurfaceTextureHelperTest {
|
||||
// Create SurfaceTextureHelper and listener.
|
||||
final SurfaceTextureHelper surfaceTextureHelper =
|
||||
SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
|
||||
surfaceTextureHelper.setTextureSize(/* textureWidth= */ 32, /* textureHeight= */ 32);
|
||||
final MockTextureListener listener = new MockTextureListener();
|
||||
surfaceTextureHelper.startListening(listener);
|
||||
// Create EglBase with the SurfaceTexture as target EGLSurface.
|
||||
@ -313,13 +309,12 @@ public class SurfaceTextureHelperTest {
|
||||
eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
|
||||
eglBase.makeCurrent();
|
||||
// Assert no frame has been received yet.
|
||||
assertFalse(listener.waitForNewFrame(1));
|
||||
listener.assertNoFrameIsDelivered(/* waitPeriodMs= */ 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();
|
||||
listener.waitForTextureBuffer().release();
|
||||
|
||||
// Stop listening - we should not receive any textures after this.
|
||||
surfaceTextureHelper.stopListening();
|
||||
@ -329,7 +324,7 @@ public class SurfaceTextureHelperTest {
|
||||
eglBase.swapBuffers();
|
||||
// swapBuffers() should not trigger onTextureFrameAvailable() because disposed has been called.
|
||||
// Assert that no OES texture was delivered.
|
||||
assertFalse(listener.waitForNewFrame(500));
|
||||
listener.assertNoFrameIsDelivered(/* waitPeriodMs= */ 500);
|
||||
|
||||
surfaceTextureHelper.dispose();
|
||||
eglBase.release();
|
||||
@ -402,6 +397,7 @@ public class SurfaceTextureHelperTest {
|
||||
// Create SurfaceTextureHelper and listener.
|
||||
final SurfaceTextureHelper surfaceTextureHelper =
|
||||
SurfaceTextureHelper.create("SurfaceTextureHelper test" /* threadName */, null);
|
||||
surfaceTextureHelper.setTextureSize(/* textureWidth= */ 32, /* textureHeight= */ 32);
|
||||
final MockTextureListener listener1 = new MockTextureListener();
|
||||
surfaceTextureHelper.startListening(listener1);
|
||||
// Create EglBase with the SurfaceTexture as target EGLSurface.
|
||||
@ -409,13 +405,12 @@ public class SurfaceTextureHelperTest {
|
||||
eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture());
|
||||
eglBase.makeCurrent();
|
||||
// Assert no frame has been received yet.
|
||||
assertFalse(listener1.waitForNewFrame(1));
|
||||
listener1.assertNoFrameIsDelivered(/* waitPeriodMs= */ 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();
|
||||
listener1.waitForTextureBuffer().release();
|
||||
|
||||
// Stop listening - |listener1| should not receive any textures after this.
|
||||
surfaceTextureHelper.stopListening();
|
||||
@ -424,17 +419,15 @@ public class SurfaceTextureHelperTest {
|
||||
final MockTextureListener listener2 = new MockTextureListener();
|
||||
surfaceTextureHelper.startListening(listener2);
|
||||
// Assert no frame has been received yet.
|
||||
assertFalse(listener2.waitForNewFrame(1));
|
||||
listener2.assertNoFrameIsDelivered(/* waitPeriodMs= */ 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();
|
||||
listener2.waitForTextureBuffer().release();
|
||||
listener1.assertNoFrameIsDelivered(/* waitPeriodMs= */ 1);
|
||||
|
||||
surfaceTextureHelper.dispose();
|
||||
eglBase.release();
|
||||
@ -480,7 +473,9 @@ public class SurfaceTextureHelperTest {
|
||||
eglBase.swapBuffers();
|
||||
|
||||
// Wait for an OES texture to arrive.
|
||||
listener.waitForNewFrame();
|
||||
final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
|
||||
final VideoFrame.I420Buffer i420 = textureBuffer.toI420();
|
||||
textureBuffer.release();
|
||||
|
||||
// Memory layout: Lines are 16 bytes. First 16 lines are
|
||||
// the Y data. These are followed by 8 lines with 8 bytes of U
|
||||
@ -496,11 +491,6 @@ public class SurfaceTextureHelperTest {
|
||||
// ...
|
||||
// 368 UUUUUUUU VVVVVVVV
|
||||
// 384 buffer end
|
||||
final VideoFrame.I420Buffer i420 =
|
||||
surfaceTextureHelper.textureToYuv(surfaceTextureHelper.createTextureBuffer(width, height,
|
||||
RendererCommon.convertMatrixToAndroidGraphicsMatrix(listener.transformMatrix)));
|
||||
|
||||
surfaceTextureHelper.returnTextureFrame();
|
||||
|
||||
// Allow off-by-one differences due to different rounding.
|
||||
final ByteBuffer dataY = i420.getDataY();
|
||||
@ -524,6 +514,7 @@ public class SurfaceTextureHelperTest {
|
||||
assertClose(1, ref_v[i], dataV.get(y * strideV + x) & 0xFF);
|
||||
}
|
||||
}
|
||||
i420.release();
|
||||
}
|
||||
|
||||
surfaceTextureHelper.dispose();
|
||||
|
@ -202,12 +202,11 @@ public class VideoFrameBufferTest {
|
||||
// Draw the frame and block until an OES texture is delivered.
|
||||
drawI420Buffer(i420Buffer);
|
||||
eglBase.swapBuffers();
|
||||
listener.waitForNewFrame();
|
||||
final VideoFrame.TextureBuffer textureBuffer = listener.waitForTextureBuffer();
|
||||
surfaceTextureHelper.stopListening();
|
||||
surfaceTextureHelper.dispose();
|
||||
|
||||
return surfaceTextureHelper.createTextureBuffer(width, height,
|
||||
RendererCommon.convertMatrixToAndroidGraphicsMatrix(listener.transformMatrix));
|
||||
return textureBuffer;
|
||||
});
|
||||
renderThread.quit();
|
||||
|
||||
|
Reference in New Issue
Block a user