VideoCapturerAndroid, only you SurfaceViewHelper when capturing to textures.

SurfaceViewHelper requires EGL14 that was added in API level 17. Since the SurfaceViewHelper is only neeed when we capture to textures, this cl change back to not use it when we are capturing to byte buffers.

Also, thread.quitsafely was added in level 18. Instead a new ThreadUtil method has been added for this.

BUG=b/24782220
TEST = run
ninja -C out/Debug libjingle_peerconnection_android_unittest && CHECKOUT_SOURCE_ROOT=`pwd` build/android/adb_install_apk.py --debug out/Debug/apks/libjingle_peerconnection_android_unittest.apk && ./third_party/android_tools/sdk/platform-tools/adb shell am instrument -w -e class org.webrtc.VideoCapturerAndroidTest org.webrtc.test/android.test.InstrumentationTestRunner on a device running Android 4.1 (I tried Nexus 7, the first version)

Review URL: https://codereview.webrtc.org/1401023003

Cr-Commit-Position: refs/heads/master@{#10265}
This commit is contained in:
perkj
2015-10-13 08:15:05 -07:00
committed by Commit bot
parent 9ea2147e5c
commit 73f44f6481
4 changed files with 91 additions and 12 deletions

View File

@ -7,7 +7,7 @@
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-sdk android:minSdkVersion="17" android:targetSdkVersion="21" />
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

View File

@ -27,17 +27,22 @@
package org.webrtc;
import android.opengl.EGL14;
import android.os.Build;
import android.test.ActivityTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.Size;
import org.webrtc.CameraEnumerationAndroid.CaptureFormat;
import java.util.HashSet;
import java.util.Set;
@SuppressWarnings("deprecation")
public class VideoCapturerAndroidTest extends ActivityTestCase {
static final String TAG = "VideoCapturerAndroidTest";
@Override
protected void setUp() {
assertTrue(PeerConnectionFactory.initializeAndroidGlobals(
@ -82,6 +87,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
@SmallTest
public void testCreateAndReleaseUsingTextures() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Log.i(TAG, "Capturing to textures is not supported, requires EGL14.");
return;
}
VideoCapturerAndroidTestFixtures.release(
VideoCapturerAndroid.create("", null, EGL14.EGL_NO_CONTEXT));
}
@ -105,6 +114,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
@SmallTest
public void testStartVideoCapturerUsingTextures() throws InterruptedException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Log.i(TAG, "Capturing to textures is not supported, requires EGL14.");
return;
}
VideoCapturerAndroid capturer =
VideoCapturerAndroid.create("", null, EGL14.EGL_NO_CONTEXT);
VideoCapturerAndroidTestFixtures.startCapturerAndRender(capturer);
@ -147,6 +160,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
@SmallTest
public void testSwitchVideoCapturerUsingTextures() throws InterruptedException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Log.i(TAG, "Capturing to textures is not supported, requires EGL14.");
return;
}
VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null, EGL14.EGL_NO_CONTEXT);
VideoCapturerAndroidTestFixtures.switchCamera(capturer);
}
@ -163,6 +180,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
@MediumTest
public void testCameraCallsAfterStopUsingTextures() throws InterruptedException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Log.i(TAG, "Capturing to textures is not supported, requires EGL14.");
return;
}
final String deviceName = CameraEnumerationAndroid.getDeviceName(0);
final VideoCapturerAndroid capturer = VideoCapturerAndroid.create(deviceName, null,
EGL14.EGL_NO_CONTEXT);
@ -181,6 +202,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
@SmallTest
public void testStopRestartVideoSourceUsingTextures() throws InterruptedException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Log.i(TAG, "Capturing to textures is not supported, requires EGL14.");
return;
}
VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null, EGL14.EGL_NO_CONTEXT);
VideoCapturerAndroidTestFixtures.stopRestartVideoSource(capturer);
}
@ -198,6 +223,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
@SmallTest
public void testStartStopWithDifferentResolutionsUsingTextures() throws InterruptedException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Log.i(TAG, "Capturing to textures is not supported, requires EGL14.");
return;
}
String deviceName = CameraEnumerationAndroid.getDeviceName(0);
VideoCapturerAndroid capturer =
VideoCapturerAndroid.create(deviceName, null, EGL14.EGL_NO_CONTEXT);
@ -218,6 +247,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
@SmallTest
public void testReturnBufferLateUsingTextures() throws InterruptedException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Log.i(TAG, "Capturing to textures is not supported, requires EGL14.");
return;
}
String deviceName = CameraEnumerationAndroid.getDeviceName(0);
VideoCapturerAndroid capturer =
VideoCapturerAndroid.create(deviceName, null, EGL14.EGL_NO_CONTEXT);
@ -236,6 +269,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
@MediumTest
public void testReturnBufferLateEndToEndUsingTextures() throws InterruptedException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Log.i(TAG, "Capturing to textures is not supported, requires EGL14.");
return;
}
final VideoCapturerAndroid capturer =
VideoCapturerAndroid.create("", null, EGL14.EGL_NO_CONTEXT);
VideoCapturerAndroidTestFixtures.returnBufferLateEndToEnd(capturer);

View File

@ -126,4 +126,18 @@ final class ThreadUtils {
awaitUninterruptibly(barrier);
return result.value;
}
/**
* Post |runner| to |handler| and wait for the result.
*/
public static void invokeUninterruptibly(final Handler handler, final Runnable runner) {
final CountDownLatch barrier = new CountDownLatch(1);
handler.post(new Runnable() {
@Override public void run() {
runner.run();
barrier.countDown();
}
});
awaitUninterruptibly(barrier);
}
}

View File

@ -28,10 +28,13 @@
package org.webrtc;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.opengl.EGL14;
import android.opengl.EGLContext;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
@ -92,6 +95,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
private CapturerObserver frameObserver = null;
private final CameraErrorHandler errorHandler;
private final boolean isCapturingToTexture;
// |cameraGlTexture| is used with setPreviewTexture if the capturer is capturing to
// ByteBuffers.
private int cameraGlTexture;
// |cameraSurfaceTexture| is used with setPreviewTexture if the capturer is capturing to
// ByteBuffers. Must be a member, see issue webrtc:5021.
private SurfaceTexture cameraSurfaceTexture;
//|surfaceHelper| is used if the capturer is capturing to a texture. Capturing to textures require
// API level 17.
private final SurfaceTextureHelper surfaceHelper;
// The camera API can output one old frame after the camera has been switched or the resolution
// has been changed. This flag is used for dropping the first frame after camera restart.
@ -204,14 +215,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
}
public static VideoCapturerAndroid create(String name,
CameraErrorHandler errorHandler, EGLContext sharedContext) {
CameraErrorHandler errorHandler, Object sharedEglContext) {
final int cameraId = lookupDeviceName(name);
if (cameraId == -1) {
return null;
}
final VideoCapturerAndroid capturer = new VideoCapturerAndroid(cameraId, errorHandler,
sharedContext);
sharedEglContext);
capturer.setNativeCapturer(nativeCreateVideoCapturer(capturer));
return capturer;
}
@ -317,7 +328,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
}
private VideoCapturerAndroid(int cameraId, CameraErrorHandler errorHandler,
EGLContext sharedContext) {
Object sharedContext) {
Logging.d(TAG, "VideoCapturerAndroid");
this.id = cameraId;
this.errorHandler = errorHandler;
@ -325,12 +336,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
cameraThread.start();
cameraThreadHandler = new Handler(cameraThread.getLooper());
videoBuffers = new FramePool(cameraThread);
surfaceHelper = SurfaceTextureHelper.create(
sharedContext == null ? EGL14.EGL_NO_CONTEXT : sharedContext, cameraThreadHandler);
if (sharedContext != null) {
surfaceHelper = SurfaceTextureHelper.create((EGLContext)sharedContext, cameraThreadHandler);
surfaceHelper.setListener(this);
isCapturingToTexture = true;
} else {
surfaceHelper = null;
isCapturingToTexture = false;
}
isCapturingToTexture = sharedContext != null;
}
private void checkIsOnCameraThread() {
@ -364,7 +377,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
if (isReleased()) {
throw new IllegalStateException("Already released");
}
cameraThreadHandler.post(new Runnable() {
ThreadUtils.invokeUninterruptibly(cameraThreadHandler, new Runnable() {
@Override
public void run() {
if (camera != null) {
@ -375,9 +388,10 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
}
}
});
surfaceHelper.disconnect();
cameraThread.quitSafely();
if (isCapturingToTexture) {
surfaceHelper.disconnect();
}
cameraThread.quit();
ThreadUtils.joinUninterruptibly(cameraThread);
cameraThread = null;
}
@ -428,7 +442,13 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
Camera.getCameraInfo(id, info);
}
try {
camera.setPreviewTexture(surfaceHelper.getSurfaceTexture());
if (isCapturingToTexture) {
camera.setPreviewTexture(surfaceHelper.getSurfaceTexture());
} else {
cameraGlTexture = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
cameraSurfaceTexture = new SurfaceTexture(cameraGlTexture);
camera.setPreviewTexture(cameraSurfaceTexture);
}
} catch (IOException e) {
Logging.e(TAG, "setPreviewTexture failed", error);
throw new RuntimeException(e);
@ -568,6 +588,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
Logging.d(TAG, "Release camera.");
camera.release();
camera = null;
if (cameraGlTexture != 0) {
GLES20.glDeleteTextures(1, new int[] {cameraGlTexture}, 0);
cameraGlTexture = 0;
}
if (cameraSurfaceTexture != null) {
cameraSurfaceTexture.release();
}
}
private void switchCameraOnCameraThread() {