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:
@ -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" />
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user