VideoCapturerAndroid: Add custom nativeCreateVideoCapturer()

This CL shouldn't make any functional changes. It adds a new VideoCapturerAndroid.nativeCreateVideoCapturer() instead of always using VideoCapturer.nativeCreateVideoCapturer(). The purpose is to simplify androidvideocapturer_jni and VideoCapturerAndroid.create(). This way, it is possible to use the ctor instead of VideoCapturerAndroid.init() to initialize variables, and they can be made final etc.

R=perkj@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#10171}
This commit is contained in:
perkj
2015-10-05 16:21:54 +02:00
parent 723dff1e6d
commit e0bce24065
4 changed files with 60 additions and 78 deletions

View File

@ -92,7 +92,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
private final Object pendingCameraSwitchLock = new Object();
private volatile boolean pendingCameraSwitch;
private CapturerObserver frameObserver = null;
private CameraErrorHandler errorHandler = null;
private final CameraErrorHandler errorHandler;
// Camera error callback.
private final Camera.ErrorCallback cameraErrorCallback =
@ -155,15 +155,14 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
void onCameraSwitchError(String errorDescription);
}
public static VideoCapturerAndroid create(String name,
CameraErrorHandler errorHandler) {
VideoCapturer capturer = VideoCapturer.create(name);
if (capturer != null) {
VideoCapturerAndroid capturerAndroid = (VideoCapturerAndroid) capturer;
capturerAndroid.errorHandler = errorHandler;
return capturerAndroid;
public static VideoCapturerAndroid create(String name, CameraErrorHandler errorHandler) {
final int cameraId = lookupDeviceName(name);
if (cameraId == -1) {
return null;
}
return null;
final VideoCapturerAndroid capturer = new VideoCapturerAndroid(cameraId, errorHandler);
capturer.setNativeCapturer(nativeCreateVideoCapturer(capturer));
return capturer;
}
// Switch camera to the next valid camera id. This can only be called while
@ -244,8 +243,15 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
return CameraEnumerationAndroid.getSupportedFormatsAsJson(getCurrentCameraId());
}
private VideoCapturerAndroid() {
// Called from native VideoCapturer_nativeCreateVideoCapturer.
private VideoCapturerAndroid(int cameraId) {
this(cameraId, null);
}
private VideoCapturerAndroid(int cameraId, CameraErrorHandler errorHandler) {
Logging.d(TAG, "VideoCapturerAndroid");
this.id = cameraId;
this.errorHandler = errorHandler;
cameraThread = new HandlerThread(TAG);
cameraThread.start();
cameraThreadHandler = new Handler(cameraThread.getLooper());
@ -258,30 +264,22 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
}
}
// Called by native code.
// Initializes local variables for the camera named |deviceName|. If |deviceName| is empty, the
// first available device is used in order to be compatible with the generic VideoCapturer class.
boolean init(String deviceName) {
Logging.d(TAG, "init: " + deviceName);
if (deviceName == null)
return false;
// Returns the camera index for camera with name |deviceName|, or -1 if no such camera can be
// found. If |deviceName| is empty, the first available device is used.
private static int lookupDeviceName(String deviceName) {
Logging.d(TAG, "lookupDeviceName: " + deviceName);
if (deviceName == null || Camera.getNumberOfCameras() == 0) {
return -1;
}
if (deviceName.isEmpty()) {
synchronized (cameraIdLock) {
this.id = 0;
}
return true;
} else {
for (int i = 0; i < Camera.getNumberOfCameras(); ++i) {
if (deviceName.equals(CameraEnumerationAndroid.getDeviceName(i))) {
synchronized (cameraIdLock) {
this.id = i;
}
return true;
}
return 0;
}
for (int i = 0; i < Camera.getNumberOfCameras(); ++i) {
if (deviceName.equals(CameraEnumerationAndroid.getDeviceName(i))) {
return i;
}
}
return false;
return -1;
}
// Called by native code to quit the camera thread. This needs to be done manually, otherwise the
@ -769,4 +767,6 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
private native void nativeOnOutputFormatRequest(long nativeCapturer,
int width, int height, int fps);
}
private static native long nativeCreateVideoCapturer(VideoCapturerAndroid videoCapturer);
}

View File

@ -46,22 +46,6 @@ int AndroidVideoCapturerJni::SetAndroidObjects(JNIEnv* jni,
return 0;
}
// static
rtc::scoped_refptr<AndroidVideoCapturerJni>
AndroidVideoCapturerJni::Create(JNIEnv* jni,
jobject j_video_capture,
jstring device_name) {
LOG(LS_INFO) << "AndroidVideoCapturerJni::Create";
rtc::scoped_refptr<AndroidVideoCapturerJni> capturer(
new rtc::RefCountedObject<AndroidVideoCapturerJni>(jni, j_video_capture));
if (capturer->Init(device_name)) {
return capturer;
}
LOG(LS_ERROR) << "AndroidVideoCapturerJni init fails";
return nullptr;
}
AndroidVideoCapturerJni::AndroidVideoCapturerJni(JNIEnv* jni,
jobject j_video_capturer)
: j_capturer_global_(jni, j_video_capturer),
@ -76,16 +60,6 @@ AndroidVideoCapturerJni::AndroidVideoCapturerJni(JNIEnv* jni,
thread_checker_.DetachFromThread();
}
bool AndroidVideoCapturerJni::Init(jstring device_name) {
const jmethodID m(GetMethodID(
jni(), *j_video_capturer_class_, "init", "(Ljava/lang/String;)Z"));
if (!jni()->CallBooleanMethod(*j_capturer_global_, m, device_name)) {
return false;
}
CHECK_EXCEPTION(jni()) << "error during CallVoidMethod";
return true;
}
AndroidVideoCapturerJni::~AndroidVideoCapturerJni() {
LOG(LS_INFO) << "AndroidVideoCapturerJni dtor";
jni()->CallVoidMethod(
@ -246,4 +220,14 @@ JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnOutputFormatRequest)
j_width, j_height, j_fps);
}
JOW(jlong, VideoCapturerAndroid_nativeCreateVideoCapturer)
(JNIEnv* jni, jclass, jobject j_video_capturer) {
rtc::scoped_refptr<webrtc::AndroidVideoCapturerDelegate> delegate =
new rtc::RefCountedObject<AndroidVideoCapturerJni>(jni, j_video_capturer);
rtc::scoped_ptr<cricket::VideoCapturer> capturer(
new webrtc::AndroidVideoCapturer(delegate));
// Caller takes ownership of the cricket::VideoCapturer* pointer.
return jlongFromPointer(capturer.release());
}
} // namespace webrtc_jni

View File

@ -46,12 +46,7 @@ class AndroidVideoCapturerJni : public webrtc::AndroidVideoCapturerDelegate {
public:
static int SetAndroidObjects(JNIEnv* jni, jobject appliction_context);
// Creates a new instance of AndroidVideoCapturerJni. Returns a nullptr if
// it can't be created. This happens if |device_name| is invalid.
static rtc::scoped_refptr<AndroidVideoCapturerJni> Create(
JNIEnv* jni,
jobject j_video_capture, // Instance of VideoCapturerAndroid
jstring device_name); // Name of the camera to use.
AndroidVideoCapturerJni(JNIEnv* jni, jobject j_video_capturer);
void Start(int width, int height, int framerate,
webrtc::AndroidVideoCapturer* capturer) override;
@ -68,12 +63,11 @@ class AndroidVideoCapturerJni : public webrtc::AndroidVideoCapturerDelegate {
int rotation,
int64 time_stamp);
void OnOutputFormatRequest(int width, int height, int fps);
protected:
AndroidVideoCapturerJni(JNIEnv* jni, jobject j_video_capturer);
protected:
~AndroidVideoCapturerJni();
private:
bool Init(jstring device_name);
private:
void ReturnBuffer(int64 time_stamp);
JNIEnv* jni();

View File

@ -1672,17 +1672,21 @@ JOW(jobject, VideoCapturer_nativeCreateVideoCapturer)(
#if defined(ANDROID)
jclass j_video_capturer_class(
FindClass(jni, "org/webrtc/VideoCapturerAndroid"));
const jmethodID j_videocapturer_ctor(GetMethodID(
jni, j_video_capturer_class, "<init>", "()V"));
jobject j_video_capturer = jni->NewObject(j_video_capturer_class,
j_videocapturer_ctor);
CHECK_EXCEPTION(jni) << "error during NewObject";
rtc::scoped_refptr<AndroidVideoCapturerJni> delegate =
AndroidVideoCapturerJni::Create(jni, j_video_capturer, j_device_name);
if (!delegate.get())
const int camera_id = jni->CallStaticIntMethod(
j_video_capturer_class,
GetStaticMethodID(jni, j_video_capturer_class, "lookupDeviceName",
"(Ljava/lang/String;)I"),
j_device_name);
CHECK_EXCEPTION(jni) << "error during VideoCapturerAndroid.lookupDeviceName";
if (camera_id == -1)
return nullptr;
rtc::scoped_ptr<webrtc::AndroidVideoCapturer> capturer(
jobject j_video_capturer = jni->NewObject(
j_video_capturer_class,
GetMethodID(jni, j_video_capturer_class, "<init>", "(I)V"), camera_id);
CHECK_EXCEPTION(jni) << "error during creation of VideoCapturerAndroid";
rtc::scoped_refptr<webrtc::AndroidVideoCapturerDelegate> delegate =
new rtc::RefCountedObject<AndroidVideoCapturerJni>(jni, j_video_capturer);
rtc::scoped_ptr<cricket::VideoCapturer> capturer(
new webrtc::AndroidVideoCapturer(delegate));
#else
@ -1712,7 +1716,7 @@ JOW(jobject, VideoCapturer_nativeCreateVideoCapturer)(
jni, j_video_capturer_class, "setNativeCapturer", "(J)V"));
jni->CallVoidMethod(j_video_capturer,
j_videocapturer_set_native_capturer,
(jlong)capturer.release());
jlongFromPointer(capturer.release()));
CHECK_EXCEPTION(jni) << "error during setNativeCapturer";
return j_video_capturer;
}