Android: Make VideoCapturer an interface for all VideoCapturers to implement

This CL factors out the interface that AndroidVideoCapturerJni is using to communicate with the Java counterpart. This interface is moved into VideoCapturer. The interface is not touched in this CL, and a follow-up CL is planned to simplify and improve it.

Another change is that the native part of VideoCapturer is created in PeerConnectionFactory.createVideoSource() instead of doing it immediately in the ctor.

BUG=webrtc:5519
R=perkj@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#11606}
This commit is contained in:
Magnus Jedvert
2016-02-12 17:05:29 +01:00
parent e78765bd4b
commit 5e7834e151
10 changed files with 149 additions and 185 deletions

View File

@ -50,9 +50,8 @@ public class CameraEnumerationAndroid {
public final int height;
public final int maxFramerate;
public final int minFramerate;
// TODO(hbos): If VideoCapturerAndroid.startCapture is updated to support
// other image formats then this needs to be updated and
// VideoCapturerAndroid.getSupportedFormats need to return CaptureFormats of
// TODO(hbos): If VideoCapturer.startCapture is updated to support other image formats then this
// needs to be updated and VideoCapturer.getSupportedFormats need to return CaptureFormats of
// all imageFormats.
public final int imageFormat = ImageFormat.NV21;

View File

@ -45,7 +45,8 @@ import java.util.concurrent.TimeUnit;
// camera thread. The internal *OnCameraThread() methods must check |camera| for null to check if
// the camera has been stopped.
@SuppressWarnings("deprecation")
public class VideoCapturerAndroid extends VideoCapturer implements
public class VideoCapturerAndroid implements
VideoCapturer,
android.hardware.Camera.PreviewCallback,
SurfaceTextureHelper.OnTextureFrameAvailableListener {
private final static String TAG = "VideoCapturerAndroid";
@ -196,12 +197,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements
if (cameraId == -1) {
return null;
}
final VideoCapturerAndroid capturer = new VideoCapturerAndroid(cameraId, eventsHandler,
sharedEglContext);
capturer.setNativeCapturer(
nativeCreateVideoCapturer(capturer, capturer.surfaceHelper));
return capturer;
return new VideoCapturerAndroid(cameraId, eventsHandler, sharedEglContext);
}
public void printStackTrace() {
@ -297,14 +293,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements
return isCapturingToTexture;
}
// Called from native code.
private String getSupportedFormatsAsJson() throws JSONException {
@Override
public String getSupportedFormatsAsJson() throws JSONException {
return CameraEnumerationAndroid.getSupportedFormatsAsJson(getCurrentCameraId());
}
// Called from native VideoCapturer_nativeCreateVideoCapturer.
private VideoCapturerAndroid(int cameraId) {
this(cameraId, null, null);
@Override
public SurfaceTextureHelper getSurfaceTextureHelper() {
return surfaceHelper;
}
private VideoCapturerAndroid(int cameraId, CameraEventsHandler eventsHandler,
@ -347,11 +343,12 @@ public class VideoCapturerAndroid extends VideoCapturer implements
return -1;
}
// Called by native code to quit the camera thread. This needs to be done manually, otherwise the
// thread and handler will not be garbage collected.
private void release() {
// Quits the camera thread. This needs to be done manually, otherwise the thread and handler will
// not be garbage collected.
@Override
public void dispose() {
Logging.d(TAG, "release");
if (isReleased()) {
if (isDisposed()) {
throw new IllegalStateException("Already released");
}
ThreadUtils.invokeUninterruptibly(cameraThreadHandler, new Runnable() {
@ -367,15 +364,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements
}
// Used for testing purposes to check if release() has been called.
public boolean isReleased() {
public boolean isDisposed() {
return (cameraThread == null);
}
// Called by native code.
//
// Note that this actually opens the camera, and Camera callbacks run on the
// thread that calls open(), so this is done on the CameraThread.
void startCapture(
@Override
public void startCapture(
final int width, final int height, final int framerate,
final Context applicationContext, final CapturerObserver frameObserver) {
Logging.d(TAG, "startCapture requested: " + width + "x" + height
@ -548,8 +544,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements
camera.startPreview();
}
// Called by native code. Returns true when camera is known to be stopped.
void stopCapture() throws InterruptedException {
// Blocks until camera is known to be stopped.
@Override
public void stopCapture() throws InterruptedException {
Logging.d(TAG, "stopCapture");
final CountDownLatch barrier = new CountDownLatch(1);
cameraThreadHandler.post(new Runnable() {
@ -702,75 +699,4 @@ public class VideoCapturerAndroid extends VideoCapturer implements
frameObserver.onTextureFrameCaptured(captureFormat.width, captureFormat.height, oesTextureId,
transformMatrix, rotation, timestampNs);
}
// Interface used for providing callbacks to an observer.
interface CapturerObserver {
// Notify if the camera have been started successfully or not.
// Called on a Java thread owned by VideoCapturerAndroid.
abstract void onCapturerStarted(boolean success);
// Delivers a captured frame. Called on a Java thread owned by
// VideoCapturerAndroid.
abstract void onByteBufferFrameCaptured(byte[] data, int width, int height, int rotation,
long timeStamp);
// Delivers a captured frame in a texture with id |oesTextureId|. Called on a Java thread
// owned by VideoCapturerAndroid.
abstract void onTextureFrameCaptured(
int width, int height, int oesTextureId, float[] transformMatrix, int rotation,
long timestamp);
// Requests an output format from the video capturer. Captured frames
// by the camera will be scaled/or dropped by the video capturer.
// Called on a Java thread owned by VideoCapturerAndroid.
abstract void onOutputFormatRequest(int width, int height, int framerate);
}
// An implementation of CapturerObserver that forwards all calls from
// Java to the C layer.
static class NativeObserver implements CapturerObserver {
private final long nativeCapturer;
public NativeObserver(long nativeCapturer) {
this.nativeCapturer = nativeCapturer;
}
@Override
public void onCapturerStarted(boolean success) {
nativeCapturerStarted(nativeCapturer, success);
}
@Override
public void onByteBufferFrameCaptured(byte[] data, int width, int height,
int rotation, long timeStamp) {
nativeOnByteBufferFrameCaptured(nativeCapturer, data, data.length, width, height, rotation,
timeStamp);
}
@Override
public void onTextureFrameCaptured(
int width, int height, int oesTextureId, float[] transformMatrix, int rotation,
long timestamp) {
nativeOnTextureFrameCaptured(nativeCapturer, width, height, oesTextureId, transformMatrix,
rotation, timestamp);
}
@Override
public void onOutputFormatRequest(int width, int height, int framerate) {
nativeOnOutputFormatRequest(nativeCapturer, width, height, framerate);
}
private native void nativeCapturerStarted(long nativeCapturer,
boolean success);
private native void nativeOnByteBufferFrameCaptured(long nativeCapturer,
byte[] data, int length, int width, int height, int rotation, long timeStamp);
private native void nativeOnTextureFrameCaptured(long nativeCapturer, int width, int height,
int oesTextureId, float[] transformMatrix, int rotation, long timestamp);
private native void nativeOnOutputFormatRequest(long nativeCapturer,
int width, int height, int framerate);
}
private static native long nativeCreateVideoCapturer(
VideoCapturerAndroid videoCapturer,
SurfaceTextureHelper surfaceHelper);
}