Split peerconnection_jni.cc into separate files.
For now:
java_helpers - JNI convenience functions etc. Can in theory be moved to libjingle / webrtc general one day.
classreferenceholder - app/webrtc specific Java class loader.
androidvideocapturer_jni - the jni part of the video capturer I added.
peerconnection_jni - all the rest.

This also move all jni specifics into ns webrtc_jni to avoid naming collision.

R=glaznev@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/38099004

Cr-Commit-Position: refs/heads/master@{#8363}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8363 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/java/jni/androidvideocapturer_jni.cc b/talk/app/webrtc/java/jni/androidvideocapturer_jni.cc
new file mode 100644
index 0000000..4f575b1
--- /dev/null
+++ b/talk/app/webrtc/java/jni/androidvideocapturer_jni.cc
@@ -0,0 +1,123 @@
+/*
+ * libjingle
+ * Copyright 2015 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h"
+
+#include "talk/app/webrtc/java/jni/classreferenceholder.h"
+
+namespace webrtc_jni {
+
+jobject AndroidVideoCapturerJni::application_context_ = nullptr;
+
+// static
+int AndroidVideoCapturerJni::SetAndroidObjects(JNIEnv* jni,
+                                               jobject appliction_context) {
+  if (application_context_) {
+    jni->DeleteGlobalRef(application_context_);
+  }
+  application_context_ = NewGlobalRef(jni, appliction_context);
+
+  return 0;
+}
+
+AndroidVideoCapturerJni::AndroidVideoCapturerJni(JNIEnv* jni,
+                                                 jobject j_video_capturer)
+    : j_capturer_global_(jni, j_video_capturer),
+      j_video_capturer_class_(
+          jni, FindClass(jni, "org/webrtc/VideoCapturerAndroid")),
+      j_frame_observer_class_(
+          jni,
+          FindClass(jni,
+                    "org/webrtc/VideoCapturerAndroid$NativeFrameObserver")) {
+  }
+
+AndroidVideoCapturerJni::~AndroidVideoCapturerJni() {}
+
+void AndroidVideoCapturerJni::Start(int width, int height, int framerate,
+                                    webrtc::AndroidVideoCapturer* capturer) {
+  j_frame_observer_ = NewGlobalRef(
+      jni(),
+      jni()->NewObject(*j_frame_observer_class_,
+                       GetMethodID(jni(),
+                                   *j_frame_observer_class_,
+                                   "<init>",
+                                   "(J)V"),
+                                   jlongFromPointer(capturer)));
+  CHECK_EXCEPTION(jni()) << "error during NewObject";
+
+  jmethodID m = GetMethodID(
+      jni(), *j_video_capturer_class_, "startCapture",
+      "(IIILandroid/content/Context;"
+      "Lorg/webrtc/VideoCapturerAndroid$CapturerObserver;)V");
+  jni()->CallVoidMethod(*j_capturer_global_,
+                        m, width, height,
+                        framerate,
+                        application_context_,
+                        j_frame_observer_);
+  CHECK_EXCEPTION(jni()) << "error during VideoCapturerAndroid.startCapture";
+}
+
+bool AndroidVideoCapturerJni::Stop() {
+  jmethodID m = GetMethodID(jni(), *j_video_capturer_class_,
+                            "stopCapture", "()Z");
+  jboolean result = jni()->CallBooleanMethod(*j_capturer_global_, m);
+  CHECK_EXCEPTION(jni()) << "error during VideoCapturerAndroid.stopCapture";
+  DeleteGlobalRef(jni(), j_frame_observer_);
+  return result;
+}
+
+std::string AndroidVideoCapturerJni::GetSupportedFormats() {
+  jmethodID m =
+      GetMethodID(jni(), *j_video_capturer_class_,
+                  "getSupportedFormatsAsJson", "()Ljava/lang/String;");
+  jstring j_json_caps =
+      (jstring) jni()->CallObjectMethod(*j_capturer_global_, m);
+  CHECK_EXCEPTION(jni()) << "error during supportedFormatsAsJson";
+  return JavaToStdString(jni(), j_json_caps);
+}
+
+JNIEnv* AndroidVideoCapturerJni::jni() { return AttachCurrentThreadIfNeeded(); }
+
+JOW(void, VideoCapturerAndroid_00024NativeFrameObserver_nativeOnFrameCaptured)
+    (JNIEnv* jni, jclass, jlong j_capturer, jbyteArray j_frame,
+        jint rotation, jlong ts) {
+  jbyte* bytes = jni->GetByteArrayElements(j_frame, NULL);
+  reinterpret_cast<webrtc::AndroidVideoCapturer*>(
+      j_capturer)->OnIncomingFrame(bytes, jni->GetArrayLength(j_frame),
+                                   rotation, ts);
+  jni->ReleaseByteArrayElements(j_frame, bytes, JNI_ABORT);
+}
+
+JOW(void, VideoCapturerAndroid_00024NativeFrameObserver_nativeCapturerStarted)
+    (JNIEnv* jni, jclass, jlong j_capturer, jboolean j_success) {
+  reinterpret_cast<webrtc::AndroidVideoCapturer*>(
+      j_capturer)->OnCapturerStarted(j_success);
+}
+
+}  // namespace webrtc_jni
+
diff --git a/talk/app/webrtc/java/jni/androidvideocapturer_jni.h b/talk/app/webrtc/java/jni/androidvideocapturer_jni.h
new file mode 100644
index 0000000..846905a
--- /dev/null
+++ b/talk/app/webrtc/java/jni/androidvideocapturer_jni.h
@@ -0,0 +1,69 @@
+/*
+ * libjingle
+ * Copyright 2015 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef TALK_APP_WEBRTC_JAVA_JNI_ANDROIDVIDEOCAPTURER_JNI_H_
+#define TALK_APP_WEBRTC_JAVA_JNI_ANDROIDVIDEOCAPTURER_JNI_H_
+
+#include <string>
+
+#include "talk/app/webrtc/androidvideocapturer.h"
+#include "talk/app/webrtc/java/jni/jni_helpers.h"
+
+namespace webrtc_jni {
+
+// AndroidVideoCapturerJni implements AndroidVideoCapturerDelegate.
+// The purpose of the delegate is to hide the JNI specifics from the C++ only
+// AndroidVideoCapturer.
+class AndroidVideoCapturerJni : public webrtc::AndroidVideoCapturerDelegate {
+ public:
+  static int SetAndroidObjects(JNIEnv* jni, jobject appliction_context);
+  AndroidVideoCapturerJni(JNIEnv* jni, jobject j_video_capturer);
+  ~AndroidVideoCapturerJni();
+
+  void Start(int width, int height, int framerate,
+             webrtc::AndroidVideoCapturer* capturer) override;
+  bool Stop() override;
+
+  std::string GetSupportedFormats() override;
+
+ private:
+  JNIEnv* jni();
+
+  const ScopedGlobalRef<jobject> j_capturer_global_;
+  const ScopedGlobalRef<jclass> j_video_capturer_class_;
+  const ScopedGlobalRef<jclass> j_frame_observer_class_;
+  jobject j_frame_observer_;
+
+  static jobject application_context_;
+
+  DISALLOW_COPY_AND_ASSIGN(AndroidVideoCapturerJni);
+};
+
+}  // namespace webrtc_jni
+
+#endif  // TALK_APP_WEBRTC_JAVA_JNI_ANDROIDVIDEOCAPTURER_JNI_H_
diff --git a/talk/app/webrtc/java/jni/classreferenceholder.cc b/talk/app/webrtc/java/jni/classreferenceholder.cc
new file mode 100644
index 0000000..25a1101
--- /dev/null
+++ b/talk/app/webrtc/java/jni/classreferenceholder.cc
@@ -0,0 +1,141 @@
+/*
+ * libjingle
+ * Copyright 2015 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "talk/app/webrtc/java/jni/classreferenceholder.h"
+
+#include "talk/app/webrtc/java/jni/jni_helpers.h"
+
+namespace webrtc_jni {
+
+// ClassReferenceHolder holds global reference to Java classes in app/webrtc.
+class ClassReferenceHolder {
+ public:
+  explicit ClassReferenceHolder(JNIEnv* jni);
+  ~ClassReferenceHolder();
+
+  void FreeReferences(JNIEnv* jni);
+  jclass GetClass(const std::string& name);
+
+ private:
+  void LoadClass(JNIEnv* jni, const std::string& name);
+
+  std::map<std::string, jclass> classes_;
+};
+
+// Allocated in LoadGlobalClassReferenceHolder(),
+// freed in FreeGlobalClassReferenceHolder().
+static ClassReferenceHolder* g_class_reference_holder = nullptr;
+
+void LoadGlobalClassReferenceHolder() {
+  CHECK(g_class_reference_holder == nullptr);
+  g_class_reference_holder = new ClassReferenceHolder(GetEnv());
+}
+
+void FreeGlobalClassReferenceHolder() {
+  g_class_reference_holder->FreeReferences(AttachCurrentThreadIfNeeded());
+  delete g_class_reference_holder;
+  g_class_reference_holder = nullptr;
+}
+
+ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) {
+  LoadClass(jni, "java/nio/ByteBuffer");
+  LoadClass(jni, "org/webrtc/AudioTrack");
+  LoadClass(jni, "org/webrtc/DataChannel");
+  LoadClass(jni, "org/webrtc/DataChannel$Buffer");
+  LoadClass(jni, "org/webrtc/DataChannel$Init");
+  LoadClass(jni, "org/webrtc/DataChannel$State");
+  LoadClass(jni, "org/webrtc/IceCandidate");
+#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
+  LoadClass(jni, "android/graphics/SurfaceTexture");
+  LoadClass(jni, "org/webrtc/VideoCapturerAndroid");
+  LoadClass(jni, "org/webrtc/VideoCapturerAndroid$NativeFrameObserver");
+  LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder");
+  LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo");
+  LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder");
+  LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder$DecoderOutputBufferInfo");
+  jclass j_decoder_class = GetClass("org/webrtc/MediaCodecVideoDecoder");
+  jmethodID j_is_egl14_supported_method = jni->GetStaticMethodID(
+      j_decoder_class, "isEGL14Supported", "()Z");
+  bool is_egl14_supported = jni->CallStaticBooleanMethod(
+      j_decoder_class, j_is_egl14_supported_method);
+  CHECK_EXCEPTION(jni);
+  if (is_egl14_supported) {
+    LoadClass(jni, "android/opengl/EGLContext");
+  }
+#endif
+  LoadClass(jni, "org/webrtc/MediaSource$State");
+  LoadClass(jni, "org/webrtc/MediaStream");
+  LoadClass(jni, "org/webrtc/MediaStreamTrack$State");
+  LoadClass(jni, "org/webrtc/PeerConnection$IceConnectionState");
+  LoadClass(jni, "org/webrtc/PeerConnection$IceGatheringState");
+  LoadClass(jni, "org/webrtc/PeerConnection$SignalingState");
+  LoadClass(jni, "org/webrtc/SessionDescription");
+  LoadClass(jni, "org/webrtc/SessionDescription$Type");
+  LoadClass(jni, "org/webrtc/StatsReport");
+  LoadClass(jni, "org/webrtc/StatsReport$Value");
+  LoadClass(jni, "org/webrtc/VideoRenderer$I420Frame");
+  LoadClass(jni, "org/webrtc/VideoCapturer");
+  LoadClass(jni, "org/webrtc/VideoTrack");
+}
+
+ClassReferenceHolder::~ClassReferenceHolder() {
+  CHECK(classes_.empty()) << "Must call FreeReferences() before dtor!";
+}
+
+void ClassReferenceHolder::FreeReferences(JNIEnv* jni) {
+  for (std::map<std::string, jclass>::const_iterator it = classes_.begin();
+      it != classes_.end(); ++it) {
+    jni->DeleteGlobalRef(it->second);
+  }
+  classes_.clear();
+}
+
+jclass ClassReferenceHolder::GetClass(const std::string& name) {
+  std::map<std::string, jclass>::iterator it = classes_.find(name);
+  CHECK(it != classes_.end()) << "Unexpected GetClass() call for: " << name;
+  return it->second;
+}
+
+void ClassReferenceHolder::LoadClass(JNIEnv* jni, const std::string& name) {
+  jclass localRef = jni->FindClass(name.c_str());
+  CHECK_EXCEPTION(jni) << "error during FindClass: " << name;
+  CHECK(localRef) << name;
+  jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef));
+  CHECK_EXCEPTION(jni) << "error during NewGlobalRef: " << name;
+  CHECK(globalRef) << name;
+  bool inserted = classes_.insert(std::make_pair(name, globalRef)).second;
+  CHECK(inserted) << "Duplicate class name: " << name;
+}
+
+// Returns a global reference guaranteed to be valid for the lifetime of the
+// process.
+jclass FindClass(JNIEnv* jni, const char* name) {
+  return g_class_reference_holder->GetClass(name);
+}
+
+}  // namespace webrtc_jni
+
diff --git a/talk/app/webrtc/java/jni/classreferenceholder.h b/talk/app/webrtc/java/jni/classreferenceholder.h
new file mode 100644
index 0000000..46e018b
--- /dev/null
+++ b/talk/app/webrtc/java/jni/classreferenceholder.h
@@ -0,0 +1,59 @@
+/*
+ * libjingle
+ * Copyright 2015 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+// Android's FindClass() is trickier than usual because the app-specific
+// ClassLoader is not consulted when there is no app-specific frame on the
+// stack.  Consequently, we only look up all classes once in app/webrtc.
+// http://developer.android.com/training/articles/perf-jni.html#faq_FindClass
+
+#ifndef TALK_APP_WEBRTC_JAVA_JNI_CLASSREFERENCEHOLDER_H_
+#define TALK_APP_WEBRTC_JAVA_JNI_CLASSREFERENCEHOLDER_H_
+
+#include <jni.h>
+#include <string>
+#include <map>
+
+namespace webrtc_jni {
+
+// LoadGlobalClassReferenceHolder must be called in JNI_OnLoad.
+void LoadGlobalClassReferenceHolder();
+// FreeGlobalClassReferenceHolder must be called in JNI_UnLoad.
+void FreeGlobalClassReferenceHolder();
+
+// Returns a global reference guaranteed to be valid for the lifetime of the
+// process.
+jclass FindClass(JNIEnv* jni, const char* name);
+
+// Convenience macro defining JNI-accessible methods in the org.webrtc package.
+// Eliminates unnecessary boilerplate and line-wraps, reducing visual clutter.
+#define JOW(rettype, name) extern "C" rettype JNIEXPORT JNICALL \
+  Java_org_webrtc_##name
+
+}  // namespace webrtc_jni
+
+#endif  // TALK_APP_WEBRTC_JAVA_JNI_CLASSREFERENCEHOLDER_H_
diff --git a/talk/app/webrtc/java/jni/jni_helpers.cc b/talk/app/webrtc/java/jni/jni_helpers.cc
new file mode 100644
index 0000000..c4e6e67
--- /dev/null
+++ b/talk/app/webrtc/java/jni/jni_helpers.cc
@@ -0,0 +1,295 @@
+
+/*
+ * libjingle
+ * Copyright 2015 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "talk/app/webrtc/java/jni/jni_helpers.h"
+
+#include <asm/unistd.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+namespace webrtc_jni {
+
+static JavaVM* g_jvm = nullptr;
+
+static pthread_once_t g_jni_ptr_once = PTHREAD_ONCE_INIT;
+
+// Key for per-thread JNIEnv* data.  Non-NULL in threads attached to |g_jvm| by
+// AttachCurrentThreadIfNeeded(), NULL in unattached threads and threads that
+// were attached by the JVM because of a Java->native call.
+static pthread_key_t g_jni_ptr;
+
+using icu::UnicodeString;
+
+JavaVM *GetJVM() {
+  CHECK(g_jvm) << "JNI_OnLoad failed to run?";
+  return g_jvm;
+}
+
+// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
+JNIEnv* GetEnv() {
+  void* env = NULL;
+  jint status = g_jvm->GetEnv(&env, JNI_VERSION_1_6);
+  CHECK(((env != NULL) && (status == JNI_OK)) ||
+        ((env == NULL) && (status == JNI_EDETACHED)))
+      << "Unexpected GetEnv return: " << status << ":" << env;
+  return reinterpret_cast<JNIEnv*>(env);
+}
+
+static void ThreadDestructor(void* prev_jni_ptr) {
+  // This function only runs on threads where |g_jni_ptr| is non-NULL, meaning
+  // we were responsible for originally attaching the thread, so are responsible
+  // for detaching it now.  However, because some JVM implementations (notably
+  // Oracle's http://goo.gl/eHApYT) also use the pthread_key_create mechanism,
+  // the JVMs accounting info for this thread may already be wiped out by the
+  // time this is called. Thus it may appear we are already detached even though
+  // it was our responsibility to detach!  Oh well.
+  if (!GetEnv())
+    return;
+
+  CHECK(GetEnv() == prev_jni_ptr)
+      << "Detaching from another thread: " << prev_jni_ptr << ":" << GetEnv();
+  jint status = g_jvm->DetachCurrentThread();
+  CHECK(status == JNI_OK) << "Failed to detach thread: " << status;
+  CHECK(!GetEnv()) << "Detaching was a successful no-op???";
+}
+
+static void CreateJNIPtrKey() {
+  CHECK(!pthread_key_create(&g_jni_ptr, &ThreadDestructor))
+      << "pthread_key_create";
+}
+
+jint InitGlobalJniVariables(JavaVM *jvm) {
+  CHECK(!g_jvm) << "InitGlobalJniVariables!";
+  g_jvm = jvm;
+  CHECK(g_jvm) << "InitGlobalJniVariables handed NULL?";
+
+  CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once";
+
+  JNIEnv* jni = nullptr;
+  if (jvm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6) != JNI_OK)
+    return -1;
+
+  return JNI_VERSION_1_6;
+}
+
+// Return thread ID as a string.
+static std::string GetThreadId() {
+  char buf[21];  // Big enough to hold a kuint64max plus terminating NULL.
+  CHECK_LT(snprintf(buf, sizeof(buf), "%llu", syscall(__NR_gettid)),
+           sizeof(buf))
+      << "Thread id is bigger than uint64??";
+  return std::string(buf);
+}
+
+// Return the current thread's name.
+static std::string GetThreadName() {
+  char name[17];
+  CHECK_EQ(0, prctl(PR_GET_NAME, name)) << "prctl(PR_GET_NAME) failed";
+  name[16] = '\0';
+  return std::string(name);
+}
+
+// Return a |JNIEnv*| usable on this thread.  Attaches to |g_jvm| if necessary.
+JNIEnv* AttachCurrentThreadIfNeeded() {
+  JNIEnv* jni = GetEnv();
+  if (jni)
+    return jni;
+  CHECK(!pthread_getspecific(g_jni_ptr))
+      << "TLS has a JNIEnv* but not attached?";
+
+  std::string name(GetThreadName() + " - " + GetThreadId());
+  JavaVMAttachArgs args;
+  args.version = JNI_VERSION_1_6;
+  args.name = &name[0];
+  args.group = NULL;
+  // Deal with difference in signatures between Oracle's jni.h and Android's.
+#ifdef _JAVASOFT_JNI_H_  // Oracle's jni.h violates the JNI spec!
+  void* env = NULL;
+#else
+  JNIEnv* env = NULL;
+#endif
+  CHECK(!g_jvm->AttachCurrentThread(&env, &args)) << "Failed to attach thread";
+  CHECK(env) << "AttachCurrentThread handed back NULL!";
+  jni = reinterpret_cast<JNIEnv*>(env);
+  CHECK(!pthread_setspecific(g_jni_ptr, jni)) << "pthread_setspecific";
+  return jni;
+}
+
+// Return a |jlong| that will correctly convert back to |ptr|.  This is needed
+// because the alternative (of silently passing a 32-bit pointer to a vararg
+// function expecting a 64-bit param) picks up garbage in the high 32 bits.
+jlong jlongFromPointer(void* ptr) {
+  static_assert(sizeof(intptr_t) <= sizeof(jlong),
+                "Time to rethink the use of jlongs");
+  // Going through intptr_t to be obvious about the definedness of the
+  // conversion from pointer to integral type.  intptr_t to jlong is a standard
+  // widening by the static_assert above.
+  jlong ret = reinterpret_cast<intptr_t>(ptr);
+  DCHECK(reinterpret_cast<void*>(ret) == ptr);
+  return ret;
+}
+
+// JNIEnv-helper methods that CHECK success: no Java exception thrown and found
+// object/class/method/field is non-null.
+jmethodID GetMethodID(
+    JNIEnv* jni, jclass c, const std::string& name, const char* signature) {
+  jmethodID m = jni->GetMethodID(c, name.c_str(), signature);
+  CHECK_EXCEPTION(jni) << "error during GetMethodID: " << name << ", "
+                       << signature;
+  CHECK(m) << name << ", " << signature;
+  return m;
+}
+
+jmethodID GetStaticMethodID(
+    JNIEnv* jni, jclass c, const char* name, const char* signature) {
+  jmethodID m = jni->GetStaticMethodID(c, name, signature);
+  CHECK_EXCEPTION(jni) << "error during GetStaticMethodID: " << name << ", "
+                       << signature;
+  CHECK(m) << name << ", " << signature;
+  return m;
+}
+
+jfieldID GetFieldID(
+    JNIEnv* jni, jclass c, const char* name, const char* signature) {
+  jfieldID f = jni->GetFieldID(c, name, signature);
+  CHECK_EXCEPTION(jni) << "error during GetFieldID";
+  CHECK(f) << name << ", " << signature;
+  return f;
+}
+
+jclass GetObjectClass(JNIEnv* jni, jobject object) {
+  jclass c = jni->GetObjectClass(object);
+  CHECK_EXCEPTION(jni) << "error during GetObjectClass";
+  CHECK(c) << "GetObjectClass returned NULL";
+  return c;
+}
+
+jobject GetObjectField(JNIEnv* jni, jobject object, jfieldID id) {
+  jobject o = jni->GetObjectField(object, id);
+  CHECK_EXCEPTION(jni) << "error during GetObjectField";
+  CHECK(o) << "GetObjectField returned NULL";
+  return o;
+}
+
+jstring GetStringField(JNIEnv* jni, jobject object, jfieldID id) {
+  return static_cast<jstring>(GetObjectField(jni, object, id));
+}
+
+jlong GetLongField(JNIEnv* jni, jobject object, jfieldID id) {
+  jlong l = jni->GetLongField(object, id);
+  CHECK_EXCEPTION(jni) << "error during GetLongField";
+  return l;
+}
+
+jint GetIntField(JNIEnv* jni, jobject object, jfieldID id) {
+  jint i = jni->GetIntField(object, id);
+  CHECK_EXCEPTION(jni) << "error during GetIntField";
+  return i;
+}
+
+bool GetBooleanField(JNIEnv* jni, jobject object, jfieldID id) {
+  jboolean b = jni->GetBooleanField(object, id);
+  CHECK_EXCEPTION(jni) << "error during GetBooleanField";
+  return b;
+}
+
+// Java references to "null" can only be distinguished as such in C++ by
+// creating a local reference, so this helper wraps that logic.
+bool IsNull(JNIEnv* jni, jobject obj) {
+  ScopedLocalRefFrame local_ref_frame(jni);
+  return jni->NewLocalRef(obj) == NULL;
+}
+
+// Given a UTF-8 encoded |native| string return a new (UTF-16) jstring.
+jstring JavaStringFromStdString(JNIEnv* jni, const std::string& native) {
+  UnicodeString ustr(UnicodeString::fromUTF8(native));
+  jstring jstr = jni->NewString(ustr.getBuffer(), ustr.length());
+  CHECK_EXCEPTION(jni) << "error during NewString";
+  return jstr;
+}
+
+// Given a (UTF-16) jstring return a new UTF-8 native string.
+std::string JavaToStdString(JNIEnv* jni, const jstring& j_string) {
+  const jchar* jchars = jni->GetStringChars(j_string, NULL);
+  CHECK_EXCEPTION(jni) << "Error during GetStringChars";
+  UnicodeString ustr(jchars, jni->GetStringLength(j_string));
+  CHECK_EXCEPTION(jni) << "Error during GetStringLength";
+  jni->ReleaseStringChars(j_string, jchars);
+  CHECK_EXCEPTION(jni) << "Error during ReleaseStringChars";
+  std::string ret;
+  return ustr.toUTF8String(ret);
+}
+
+// Return the (singleton) Java Enum object corresponding to |index|;
+jobject JavaEnumFromIndex(JNIEnv* jni, jclass state_class,
+                          const std::string& state_class_name, int index) {
+  jmethodID state_values_id = GetStaticMethodID(
+      jni, state_class, "values", ("()[L" + state_class_name  + ";").c_str());
+  jobjectArray state_values = static_cast<jobjectArray>(
+      jni->CallStaticObjectMethod(state_class, state_values_id));
+  CHECK_EXCEPTION(jni) << "error during CallStaticObjectMethod";
+  jobject ret = jni->GetObjectArrayElement(state_values, index);
+  CHECK_EXCEPTION(jni) << "error during GetObjectArrayElement";
+  return ret;
+}
+
+jobject NewGlobalRef(JNIEnv* jni, jobject o) {
+  jobject ret = jni->NewGlobalRef(o);
+  CHECK_EXCEPTION(jni) << "error during NewGlobalRef";
+  CHECK(ret);
+  return ret;
+}
+
+void DeleteGlobalRef(JNIEnv* jni, jobject o) {
+  jni->DeleteGlobalRef(o);
+  CHECK_EXCEPTION(jni) << "error during DeleteGlobalRef";
+}
+
+WeakRef::WeakRef(JNIEnv* jni, jweak ref)
+      : jni_(jni), obj_(jni_->NewLocalRef(ref)) {
+    CHECK_EXCEPTION(jni) << "error during NewLocalRef";
+}
+WeakRef::~WeakRef() {
+  if (obj_) {
+    jni_->DeleteLocalRef(obj_);
+    CHECK_EXCEPTION(jni_) << "error during DeleteLocalRef";
+  }
+}
+
+// Scope Java local references to the lifetime of this object.  Use in all C++
+// callbacks (i.e. entry points that don't originate in a Java callstack
+// through a "native" method call).
+ScopedLocalRefFrame::ScopedLocalRefFrame(JNIEnv* jni) : jni_(jni) {
+  CHECK(!jni_->PushLocalFrame(0)) << "Failed to PushLocalFrame";
+}
+ScopedLocalRefFrame::~ScopedLocalRefFrame() {
+  jni_->PopLocalFrame(NULL);
+}
+
+}  // namespace webrtc_jni
diff --git a/talk/app/webrtc/java/jni/jni_helpers.h b/talk/app/webrtc/java/jni/jni_helpers.h
new file mode 100644
index 0000000..bfbde78
--- /dev/null
+++ b/talk/app/webrtc/java/jni/jni_helpers.h
@@ -0,0 +1,156 @@
+/*
+ * libjingle
+ * Copyright 2015 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+// This file contain convenience functions and classes for JNI.
+// Before using any of the methods, InitGlobalJniVariables must be called.
+
+#ifndef TALK_APP_WEBRTC_JAVA_JNI_JNI_HELPERS_H_
+#define TALK_APP_WEBRTC_JAVA_JNI_JNI_HELPERS_H_
+
+#include <jni.h>
+#include <string>
+
+#include "webrtc/base/checks.h"
+#include "third_party/icu/source/common/unicode/unistr.h"
+
+// Abort the process if |jni| has a Java exception pending.
+// This macros uses the comma operator to execute ExceptionDescribe
+// and ExceptionClear ignoring their return values and sending ""
+// to the error stream.
+#define CHECK_EXCEPTION(jni)    \
+  CHECK(!jni->ExceptionCheck()) \
+      << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
+
+// Helper that calls ptr->Release() and aborts the process with a useful
+// message if that didn't actually delete *ptr because of extra refcounts.
+#define CHECK_RELEASE(ptr) \
+  CHECK_EQ(0, (ptr)->Release()) << "Unexpected refcount."
+
+namespace webrtc_jni {
+
+jint InitGlobalJniVariables(JavaVM *jvm);
+
+// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
+JNIEnv* GetEnv();
+
+JavaVM *GetJVM();
+
+// Return a |JNIEnv*| usable on this thread.  Attaches to |g_jvm| if necessary.
+JNIEnv* AttachCurrentThreadIfNeeded();
+
+// Return a |jlong| that will correctly convert back to |ptr|.  This is needed
+// because the alternative (of silently passing a 32-bit pointer to a vararg
+// function expecting a 64-bit param) picks up garbage in the high 32 bits.
+jlong jlongFromPointer(void* ptr);
+
+// JNIEnv-helper methods that CHECK success: no Java exception thrown and found
+// object/class/method/field is non-null.
+jmethodID GetMethodID(
+    JNIEnv* jni, jclass c, const std::string& name, const char* signature);
+
+jmethodID GetStaticMethodID(
+    JNIEnv* jni, jclass c, const char* name, const char* signature);
+
+jfieldID GetFieldID(JNIEnv* jni, jclass c, const char* name,
+                    const char* signature);
+
+jclass GetObjectClass(JNIEnv* jni, jobject object);
+
+jobject GetObjectField(JNIEnv* jni, jobject object, jfieldID id);
+
+jstring GetStringField(JNIEnv* jni, jobject object, jfieldID id);
+
+jlong GetLongField(JNIEnv* jni, jobject object, jfieldID id);
+
+jint GetIntField(JNIEnv* jni, jobject object, jfieldID id);
+
+bool GetBooleanField(JNIEnv* jni, jobject object, jfieldID id);
+
+// Java references to "null" can only be distinguished as such in C++ by
+// creating a local reference, so this helper wraps that logic.
+bool IsNull(JNIEnv* jni, jobject obj);
+
+// Given a UTF-8 encoded |native| string return a new (UTF-16) jstring.
+jstring JavaStringFromStdString(JNIEnv* jni, const std::string& native);
+
+// Given a (UTF-16) jstring return a new UTF-8 native string.
+std::string JavaToStdString(JNIEnv* jni, const jstring& j_string);
+
+// Return the (singleton) Java Enum object corresponding to |index|;
+jobject JavaEnumFromIndex(JNIEnv* jni, jclass state_class,
+                          const std::string& state_class_name, int index);
+
+jobject NewGlobalRef(JNIEnv* jni, jobject o);
+
+void DeleteGlobalRef(JNIEnv* jni, jobject o);
+
+// Given a jweak reference, allocate a (strong) local reference scoped to the
+// lifetime of this object if the weak reference is still valid, or NULL
+// otherwise.
+class WeakRef {
+ public:
+  WeakRef(JNIEnv* jni, jweak ref);
+  ~WeakRef();
+  jobject obj() { return obj_; }
+
+ private:
+  JNIEnv* const jni_;
+  jobject const obj_;
+};
+
+// Scope Java local references to the lifetime of this object.  Use in all C++
+// callbacks (i.e. entry points that don't originate in a Java callstack
+// through a "native" method call).
+class ScopedLocalRefFrame {
+ public:
+  explicit ScopedLocalRefFrame(JNIEnv* jni);
+  ~ScopedLocalRefFrame();
+
+ private:
+  JNIEnv* jni_;
+};
+
+// Scoped holder for global Java refs.
+template<class T>  // T is jclass, jobject, jintArray, etc.
+class ScopedGlobalRef {
+ public:
+  ScopedGlobalRef(JNIEnv* jni, T obj)
+      : obj_(static_cast<T>(jni->NewGlobalRef(obj))) {}
+  ~ScopedGlobalRef() {
+    DeleteGlobalRef(AttachCurrentThreadIfNeeded(), obj_);
+  }
+  T operator*() const {
+    return obj_;
+  }
+ private:
+  T obj_;
+};
+
+}  // namespace webrtc_jni
+
+#endif  // TALK_APP_WEBRTC_JAVA_JNI_JNI_HELPERS_H_
diff --git a/talk/app/webrtc/java/jni/peerconnection_jni.cc b/talk/app/webrtc/java/jni/peerconnection_jni.cc
index 9c8d708..bddd417 100644
--- a/talk/app/webrtc/java/jni/peerconnection_jni.cc
+++ b/talk/app/webrtc/java/jni/peerconnection_jni.cc
@@ -56,13 +56,10 @@
 #undef JNIEXPORT
 #define JNIEXPORT __attribute__((visibility("default")))
 
-#include <asm/unistd.h>
-#include <sys/prctl.h>
-#include <sys/syscall.h>
-#include <unistd.h>
 #include <limits>
-#include <map>
 
+#include "talk/app/webrtc/java/jni/classreferenceholder.h"
+#include "talk/app/webrtc/java/jni/jni_helpers.h"
 #include "talk/app/webrtc/mediaconstraintsinterface.h"
 #include "talk/app/webrtc/peerconnectioninterface.h"
 #include "talk/app/webrtc/videosourceinterface.h"
@@ -92,6 +89,7 @@
 #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
 #include <android/log.h>
 #include "talk/app/webrtc/androidvideocapturer.h"
+#include "talk/app/webrtc/java/jni/androidvideocapturer_jni.h"
 #include "webrtc/modules/video_render/video_render_internal.h"
 #include "webrtc/system_wrappers/interface/logcat_trace_context.h"
 #include "webrtc/system_wrappers/interface/tick_util.h"
@@ -106,7 +104,6 @@
 using webrtc::VideoCodec;
 #endif
 
-using icu::UnicodeString;
 using rtc::Bind;
 using rtc::Thread;
 using rtc::ThreadManager;
@@ -139,28 +136,7 @@
 using webrtc::VideoTrackVector;
 using webrtc::kVideoCodecVP8;
 
-// Abort the process if |jni| has a Java exception pending.
-// This macros uses the comma operator to execute ExceptionDescribe
-// and ExceptionClear ignoring their return values and sending ""
-// to the error stream.
-#define CHECK_EXCEPTION(jni)    \
-  CHECK(!jni->ExceptionCheck()) \
-      << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
-
-// Helper that calls ptr->Release() and aborts the process with a useful
-// message if that didn't actually delete *ptr because of extra refcounts.
-#define CHECK_RELEASE(ptr) \
-  CHECK_EQ(0, (ptr)->Release()) << "Unexpected refcount."
-
-namespace {
-
-static JavaVM* g_jvm = NULL;  // Set in JNI_OnLoad().
-
-static pthread_once_t g_jni_ptr_once = PTHREAD_ONCE_INIT;
-// Key for per-thread JNIEnv* data.  Non-NULL in threads attached to |g_jvm| by
-// AttachCurrentThreadIfNeeded(), NULL in unattached threads and threads that
-// were attached by the JVM because of a Java->native call.
-static pthread_key_t g_jni_ptr;
+namespace webrtc_jni {
 
 // Field trials initialization string
 static char *field_trials_init_string = NULL;
@@ -171,388 +147,29 @@
 static bool vp8_hw_acceleration_enabled = true;
 #endif
 
-
-// Return thread ID as a string.
-static std::string GetThreadId() {
-  char buf[21];  // Big enough to hold a kuint64max plus terminating NULL.
-  CHECK_LT(snprintf(buf, sizeof(buf), "%llu", syscall(__NR_gettid)),
-           sizeof(buf))
-      << "Thread id is bigger than uint64??";
-  return std::string(buf);
-}
-
-// Return the current thread's name.
-static std::string GetThreadName() {
-  char name[17];
-  CHECK_EQ(0, prctl(PR_GET_NAME, name)) << "prctl(PR_GET_NAME) failed";
-  name[16] = '\0';
-  return std::string(name);
-}
-
-// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
-static JNIEnv* GetEnv() {
-  void* env = NULL;
-  jint status = g_jvm->GetEnv(&env, JNI_VERSION_1_6);
-  CHECK(((env != NULL) && (status == JNI_OK)) ||
-        ((env == NULL) && (status == JNI_EDETACHED)))
-      << "Unexpected GetEnv return: " << status << ":" << env;
-  return reinterpret_cast<JNIEnv*>(env);
-}
-
-static void ThreadDestructor(void* prev_jni_ptr) {
-  // This function only runs on threads where |g_jni_ptr| is non-NULL, meaning
-  // we were responsible for originally attaching the thread, so are responsible
-  // for detaching it now.  However, because some JVM implementations (notably
-  // Oracle's http://goo.gl/eHApYT) also use the pthread_key_create mechanism,
-  // the JVMs accounting info for this thread may already be wiped out by the
-  // time this is called. Thus it may appear we are already detached even though
-  // it was our responsibility to detach!  Oh well.
-  if (!GetEnv())
-    return;
-
-  CHECK(GetEnv() == prev_jni_ptr)
-      << "Detaching from another thread: " << prev_jni_ptr << ":" << GetEnv();
-  jint status = g_jvm->DetachCurrentThread();
-  CHECK(status == JNI_OK) << "Failed to detach thread: " << status;
-  CHECK(!GetEnv()) << "Detaching was a successful no-op???";
-}
-
-static void CreateJNIPtrKey() {
-  CHECK(!pthread_key_create(&g_jni_ptr, &ThreadDestructor))
-      << "pthread_key_create";
-}
-
-// Return a |JNIEnv*| usable on this thread.  Attaches to |g_jvm| if necessary.
-static JNIEnv* AttachCurrentThreadIfNeeded() {
-  JNIEnv* jni = GetEnv();
-  if (jni)
-    return jni;
-  CHECK(!pthread_getspecific(g_jni_ptr))
-      << "TLS has a JNIEnv* but not attached?";
-
-  char* name = strdup((GetThreadName() + " - " + GetThreadId()).c_str());
-  JavaVMAttachArgs args;
-  args.version = JNI_VERSION_1_6;
-  args.name = name;
-  args.group = NULL;
-  // Deal with difference in signatures between Oracle's jni.h and Android's.
-#ifdef _JAVASOFT_JNI_H_  // Oracle's jni.h violates the JNI spec!
-  void* env = NULL;
-#else
-  JNIEnv* env = NULL;
-#endif
-  CHECK(!g_jvm->AttachCurrentThread(&env, &args)) << "Failed to attach thread";
-  free(name);
-  CHECK(env) << "AttachCurrentThread handed back NULL!";
-  jni = reinterpret_cast<JNIEnv*>(env);
-  CHECK(!pthread_setspecific(g_jni_ptr, jni)) << "pthread_setspecific";
-  return jni;
-}
-
-// Return a |jlong| that will correctly convert back to |ptr|.  This is needed
-// because the alternative (of silently passing a 32-bit pointer to a vararg
-// function expecting a 64-bit param) picks up garbage in the high 32 bits.
-static jlong jlongFromPointer(void* ptr) {
-  static_assert(sizeof(intptr_t) <= sizeof(jlong),
-                "Time to rethink the use of jlongs");
-  // Going through intptr_t to be obvious about the definedness of the
-  // conversion from pointer to integral type.  intptr_t to jlong is a standard
-  // widening by the static_assert above.
-  jlong ret = reinterpret_cast<intptr_t>(ptr);
-  assert(reinterpret_cast<void*>(ret) == ptr);
-  return ret;
-}
-
-// Android's FindClass() is trickier than usual because the app-specific
-// ClassLoader is not consulted when there is no app-specific frame on the
-// stack.  Consequently, we only look up classes once in JNI_OnLoad.
-// http://developer.android.com/training/articles/perf-jni.html#faq_FindClass
-class ClassReferenceHolder {
- public:
-  explicit ClassReferenceHolder(JNIEnv* jni) {
-    LoadClass(jni, "java/nio/ByteBuffer");
-    LoadClass(jni, "org/webrtc/AudioTrack");
-    LoadClass(jni, "org/webrtc/DataChannel");
-    LoadClass(jni, "org/webrtc/DataChannel$Buffer");
-    LoadClass(jni, "org/webrtc/DataChannel$Init");
-    LoadClass(jni, "org/webrtc/DataChannel$State");
-    LoadClass(jni, "org/webrtc/IceCandidate");
-#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
-    LoadClass(jni, "android/graphics/SurfaceTexture");
-    LoadClass(jni, "org/webrtc/VideoCapturerAndroid");
-    LoadClass(jni, "org/webrtc/VideoCapturerAndroid$NativeFrameObserver");
-    LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder");
-    LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo");
-    LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder");
-    LoadClass(jni, "org/webrtc/MediaCodecVideoDecoder$DecoderOutputBufferInfo");
-    jclass j_decoder_class = GetClass("org/webrtc/MediaCodecVideoDecoder");
-    jmethodID j_is_egl14_supported_method = jni->GetStaticMethodID(
-        j_decoder_class, "isEGL14Supported", "()Z");
-    bool is_egl14_supported = jni->CallStaticBooleanMethod(
-        j_decoder_class, j_is_egl14_supported_method);
-    CHECK_EXCEPTION(jni);
-    if (is_egl14_supported) {
-      LoadClass(jni, "android/opengl/EGLContext");
-    }
-#endif
-    LoadClass(jni, "org/webrtc/MediaSource$State");
-    LoadClass(jni, "org/webrtc/MediaStream");
-    LoadClass(jni, "org/webrtc/MediaStreamTrack$State");
-    LoadClass(jni, "org/webrtc/PeerConnection$IceConnectionState");
-    LoadClass(jni, "org/webrtc/PeerConnection$IceGatheringState");
-    LoadClass(jni, "org/webrtc/PeerConnection$SignalingState");
-    LoadClass(jni, "org/webrtc/SessionDescription");
-    LoadClass(jni, "org/webrtc/SessionDescription$Type");
-    LoadClass(jni, "org/webrtc/StatsReport");
-    LoadClass(jni, "org/webrtc/StatsReport$Value");
-    LoadClass(jni, "org/webrtc/VideoRenderer$I420Frame");
-    LoadClass(jni, "org/webrtc/VideoCapturer");
-    LoadClass(jni, "org/webrtc/VideoTrack");
-  }
-
-  ~ClassReferenceHolder() {
-    CHECK(classes_.empty()) << "Must call FreeReferences() before dtor!";
-  }
-
-  void FreeReferences(JNIEnv* jni) {
-    for (std::map<std::string, jclass>::const_iterator it = classes_.begin();
-         it != classes_.end(); ++it) {
-      jni->DeleteGlobalRef(it->second);
-    }
-    classes_.clear();
-  }
-
-  jclass GetClass(const std::string& name) {
-    std::map<std::string, jclass>::iterator it = classes_.find(name);
-    CHECK(it != classes_.end()) << "Unexpected GetClass() call for: " << name;
-    return it->second;
-  }
-
- private:
-  void LoadClass(JNIEnv* jni, const std::string& name) {
-    jclass localRef = jni->FindClass(name.c_str());
-    CHECK_EXCEPTION(jni) << "error during FindClass: " << name;
-    CHECK(localRef) << name;
-    jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef));
-    CHECK_EXCEPTION(jni) << "error during NewGlobalRef: " << name;
-    CHECK(globalRef) << name;
-    bool inserted = classes_.insert(std::make_pair(name, globalRef)).second;
-    CHECK(inserted) << "Duplicate class name: " << name;
-  }
-
-  std::map<std::string, jclass> classes_;
-};
-
-// Allocated in JNI_OnLoad(), freed in JNI_OnUnLoad().
-static ClassReferenceHolder* g_class_reference_holder = NULL;
-
-// JNIEnv-helper methods that CHECK success: no Java exception thrown and found
-// object/class/method/field is non-null.
-jmethodID GetMethodID(
-    JNIEnv* jni, jclass c, const std::string& name, const char* signature) {
-  jmethodID m = jni->GetMethodID(c, name.c_str(), signature);
-  CHECK_EXCEPTION(jni) << "error during GetMethodID: " << name << ", "
-                       << signature;
-  CHECK(m) << name << ", " << signature;
-  return m;
-}
-
-jmethodID GetStaticMethodID(
-    JNIEnv* jni, jclass c, const char* name, const char* signature) {
-  jmethodID m = jni->GetStaticMethodID(c, name, signature);
-  CHECK_EXCEPTION(jni) << "error during GetStaticMethodID: " << name << ", "
-                       << signature;
-  CHECK(m) << name << ", " << signature;
-  return m;
-}
-
-jfieldID GetFieldID(
-    JNIEnv* jni, jclass c, const char* name, const char* signature) {
-  jfieldID f = jni->GetFieldID(c, name, signature);
-  CHECK_EXCEPTION(jni) << "error during GetFieldID";
-  CHECK(f) << name << ", " << signature;
-  return f;
-}
-
-// Returns a global reference guaranteed to be valid for the lifetime of the
-// process.
-jclass FindClass(JNIEnv* jni, const char* name) {
-  return g_class_reference_holder->GetClass(name);
-}
-
-jclass GetObjectClass(JNIEnv* jni, jobject object) {
-  jclass c = jni->GetObjectClass(object);
-  CHECK_EXCEPTION(jni) << "error during GetObjectClass";
-  CHECK(c) << "GetObjectClass returned NULL";
-  return c;
-}
-
-jobject GetObjectField(JNIEnv* jni, jobject object, jfieldID id) {
-  jobject o = jni->GetObjectField(object, id);
-  CHECK_EXCEPTION(jni) << "error during GetObjectField";
-  CHECK(o) << "GetObjectField returned NULL";
-  return o;
-}
-
-jstring GetStringField(JNIEnv* jni, jobject object, jfieldID id) {
-  return static_cast<jstring>(GetObjectField(jni, object, id));
-}
-
-jlong GetLongField(JNIEnv* jni, jobject object, jfieldID id) {
-  jlong l = jni->GetLongField(object, id);
-  CHECK_EXCEPTION(jni) << "error during GetLongField";
-  return l;
-}
-
-jint GetIntField(JNIEnv* jni, jobject object, jfieldID id) {
-  jint i = jni->GetIntField(object, id);
-  CHECK_EXCEPTION(jni) << "error during GetIntField";
-  return i;
-}
-
-bool GetBooleanField(JNIEnv* jni, jobject object, jfieldID id) {
-  jboolean b = jni->GetBooleanField(object, id);
-  CHECK_EXCEPTION(jni) << "error during GetBooleanField";
-  return b;
-}
-
-jobject NewGlobalRef(JNIEnv* jni, jobject o) {
-  jobject ret = jni->NewGlobalRef(o);
-  CHECK_EXCEPTION(jni) << "error during NewGlobalRef";
-  CHECK(ret);
-  return ret;
-}
-
-void DeleteGlobalRef(JNIEnv* jni, jobject o) {
-  jni->DeleteGlobalRef(o);
-  CHECK_EXCEPTION(jni) << "error during DeleteGlobalRef";
-}
-
-// Convenience macro defining JNI-accessible methods in the org.webrtc package.
-// Eliminates unnecessary boilerplate and line-wraps, reducing visual clutter.
-#define JOW(rettype, name) extern "C" rettype JNIEXPORT JNICALL \
-  Java_org_webrtc_##name
-
 extern "C" jint JNIEXPORT JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
-  CHECK(!g_jvm) << "JNI_OnLoad called more than once!";
-  g_jvm = jvm;
-  CHECK(g_jvm) << "JNI_OnLoad handed NULL?";
-
-  CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once";
+  jint ret = InitGlobalJniVariables(jvm);
+  if (ret < 0)
+    return -1;
 
   CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
+  LoadGlobalClassReferenceHolder();
 
-  JNIEnv* jni;
-  if (jvm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6) != JNI_OK)
-    return -1;
-  g_class_reference_holder = new ClassReferenceHolder(jni);
-
-  return JNI_VERSION_1_6;
+  return ret;
 }
 
 extern "C" void JNIEXPORT JNICALL JNI_OnUnLoad(JavaVM *jvm, void *reserved) {
-  g_class_reference_holder->FreeReferences(AttachCurrentThreadIfNeeded());
-  delete g_class_reference_holder;
-  g_class_reference_holder = NULL;
+  FreeGlobalClassReferenceHolder();
   CHECK(rtc::CleanupSSL()) << "Failed to CleanupSSL()";
-  g_jvm = NULL;
-}
-
-// Given a jweak reference, allocate a (strong) local reference scoped to the
-// lifetime of this object if the weak reference is still valid, or NULL
-// otherwise.
-class WeakRef {
- public:
-  WeakRef(JNIEnv* jni, jweak ref)
-      : jni_(jni), obj_(jni_->NewLocalRef(ref)) {
-    CHECK_EXCEPTION(jni) << "error during NewLocalRef";
-  }
-  ~WeakRef() {
-    if (obj_) {
-      jni_->DeleteLocalRef(obj_);
-      CHECK_EXCEPTION(jni_) << "error during DeleteLocalRef";
-    }
-  }
-  jobject obj() { return obj_; }
-
- private:
-  JNIEnv* const jni_;
-  jobject const obj_;
-};
-
-// Scope Java local references to the lifetime of this object.  Use in all C++
-// callbacks (i.e. entry points that don't originate in a Java callstack
-// through a "native" method call).
-class ScopedLocalRefFrame {
- public:
-  explicit ScopedLocalRefFrame(JNIEnv* jni) : jni_(jni) {
-    CHECK(!jni_->PushLocalFrame(0)) << "Failed to PushLocalFrame";
-  }
-  ~ScopedLocalRefFrame() {
-    jni_->PopLocalFrame(NULL);
-  }
-
- private:
-  JNIEnv* jni_;
-};
-
-// Scoped holder for global Java refs.
-template<class T>  // T is jclass, jobject, jintArray, etc.
-class ScopedGlobalRef {
- public:
-  ScopedGlobalRef(JNIEnv* jni, T obj)
-      : obj_(static_cast<T>(jni->NewGlobalRef(obj))) {}
-  ~ScopedGlobalRef() {
-    DeleteGlobalRef(AttachCurrentThreadIfNeeded(), obj_);
-  }
-  T operator*() const {
-    return obj_;
-  }
- private:
-  T obj_;
-};
-
-// Java references to "null" can only be distinguished as such in C++ by
-// creating a local reference, so this helper wraps that logic.
-static bool IsNull(JNIEnv* jni, jobject obj) {
-  ScopedLocalRefFrame local_ref_frame(jni);
-  return jni->NewLocalRef(obj) == NULL;
 }
 
 // Return the (singleton) Java Enum object corresponding to |index|;
 // |state_class_fragment| is something like "MediaSource$State".
 jobject JavaEnumFromIndex(
     JNIEnv* jni, const std::string& state_class_fragment, int index) {
-  std::string state_class_name = "org/webrtc/" + state_class_fragment;
-  jclass state_class = FindClass(jni, state_class_name.c_str());
-  jmethodID state_values_id = GetStaticMethodID(
-      jni, state_class, "values", ("()[L" + state_class_name  + ";").c_str());
-  jobjectArray state_values = static_cast<jobjectArray>(
-      jni->CallStaticObjectMethod(state_class, state_values_id));
-  CHECK_EXCEPTION(jni) << "error during CallStaticObjectMethod";
-  jobject ret = jni->GetObjectArrayElement(state_values, index);
-  CHECK_EXCEPTION(jni) << "error during GetObjectArrayElement";
-  return ret;
-}
-
-// Given a UTF-8 encoded |native| string return a new (UTF-16) jstring.
-static jstring JavaStringFromStdString(JNIEnv* jni, const std::string& native) {
-  UnicodeString ustr(UnicodeString::fromUTF8(native));
-  jstring jstr = jni->NewString(ustr.getBuffer(), ustr.length());
-  CHECK_EXCEPTION(jni) << "error during NewString";
-  return jstr;
-}
-
-// Given a (UTF-16) jstring return a new UTF-8 native string.
-static std::string JavaToStdString(JNIEnv* jni, const jstring& j_string) {
-  const jchar* jchars = jni->GetStringChars(j_string, NULL);
-  CHECK_EXCEPTION(jni) << "Error during GetStringChars";
-  UnicodeString ustr(jchars, jni->GetStringLength(j_string));
-  CHECK_EXCEPTION(jni) << "Error during GetStringLength";
-  jni->ReleaseStringChars(j_string, jchars);
-  CHECK_EXCEPTION(jni) << "Error during ReleaseStringChars";
-  std::string ret;
-  return ustr.toUTF8String(ret);
+  const std::string state_class = "org/webrtc/" + state_class_fragment;
+  return JavaEnumFromIndex(jni, FindClass(jni, state_class.c_str()),
+                           state_class, index);
 }
 
 static DataChannelInit JavaDataChannelInitToNative(
@@ -1242,7 +859,7 @@
 // into its own .h/.cc pair, if/when the JNI helper stuff above is extracted
 // from this file.
 
-//#define TRACK_BUFFER_TIMING
+// #define TRACK_BUFFER_TIMING
 #define TAG "MediaCodecVideo"
 #ifdef TRACK_BUFFER_TIMING
 #define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
@@ -1377,7 +994,7 @@
   int height_;  // Frame height in pixels.
   bool inited_;
   uint16_t picture_id_;
-  enum libyuv::FourCC encoder_fourcc_; // Encoder color space format.
+  enum libyuv::FourCC encoder_fourcc_;  // Encoder color space format.
   int last_set_bitrate_kbps_;  // Last-requested bitrate in kbps.
   int last_set_fps_;  // Last-requested frame rate.
   int64_t current_timestamp_us_;  // Current frame timestamps in us.
@@ -1764,7 +1381,7 @@
   CheckOnCodecThread();
   JNIEnv* jni = AttachCurrentThreadIfNeeded();
   ALOGD("EncoderRelease: Frames received: %d. Frames dropped: %d.",
-      frames_received_,frames_dropped_);
+      frames_received_, frames_dropped_);
   ScopedLocalRefFrame local_ref_frame(jni);
   for (size_t i = 0; i < input_buffers_.size(); ++i)
     jni->DeleteGlobalRef(input_buffers_[i]);
@@ -1888,7 +1505,7 @@
           current_encoding_time_ms_ / current_frames_, statistic_time_ms);
       start_time_ms_ = GetCurrentTimeMs();
       current_frames_ = 0;
-      current_bytes_= 0;
+      current_bytes_ = 0;
       current_encoding_time_ms_ = 0;
     }
 
@@ -2517,7 +2134,8 @@
       decoded_image_.CreateFrame(
           stride * slice_height, payload,
           (stride * slice_height) / 4, payload + (stride * slice_height),
-          (stride * slice_height) / 4, payload + (5 * stride * slice_height / 4),
+          (stride * slice_height) / 4,
+          payload + (5 * stride * slice_height / 4),
           width, height,
           stride, stride / 2, stride / 2);
     } else {
@@ -2575,7 +2193,7 @@
         current_decoding_time_ms_ / current_frames_, statistic_time_ms);
     start_time_ms_ = GetCurrentTimeMs();
     current_frames_ = 0;
-    current_bytes_= 0;
+    current_bytes_ = 0;
     current_decoding_time_ms_ = 0;
   }
 
@@ -2672,108 +2290,8 @@
   delete decoder;
 }
 
-// AndroidVideoCapturerJni implements AndroidVideoCapturerDelegate.
-// The purpose of the delegate is to hide the JNI specifics from the C++ only
-// AndroidVideoCapturer.
-// TODO(perkj): Refactor this to a separate file once the jni utility functions
-// and classes have been moved.
-class AndroidVideoCapturerJni : public webrtc::AndroidVideoCapturerDelegate {
- public:
-  static int SetAndroidObjects(JNIEnv* jni, jobject appliction_context) {
-    if (application_context_) {
-      jni->DeleteGlobalRef(application_context_);
-    }
-    application_context_ = NewGlobalRef(jni, appliction_context);
-
-    return 0;
-  }
-
-  AndroidVideoCapturerJni(JNIEnv* jni, jobject j_video_capturer)
-      : j_capturer_global_(jni, j_video_capturer),
-        j_video_capturer_class_(
-            jni, FindClass(jni, "org/webrtc/VideoCapturerAndroid")),
-        j_frame_observer_class_(
-            jni,
-            FindClass(jni,
-                      "org/webrtc/VideoCapturerAndroid$NativeFrameObserver")) {
-  }
-
-  void Start(int width, int height, int framerate,
-             webrtc::AndroidVideoCapturer* capturer) override {
-    j_frame_observer_ = NewGlobalRef(
-        jni(),
-        jni()->NewObject(*j_frame_observer_class_,
-                         GetMethodID(jni(),
-                                     *j_frame_observer_class_,
-                                     "<init>",
-                                     "(J)V"),
-                         jlongFromPointer(capturer)));
-    CHECK_EXCEPTION(jni()) << "error during NewObject";
-
-    jmethodID m = GetMethodID(
-        jni(), *j_video_capturer_class_, "startCapture",
-        "(IIILandroid/content/Context;"
-        "Lorg/webrtc/VideoCapturerAndroid$CapturerObserver;)V");
-    jni()->CallVoidMethod(*j_capturer_global_,
-                          m, width, height,
-                          framerate,
-                          application_context_,
-                          j_frame_observer_);
-    CHECK_EXCEPTION(jni()) << "error during VideoCapturerAndroid.startCapture";
-  }
-
-  bool Stop() override {
-    jmethodID m = GetMethodID(jni(), *j_video_capturer_class_,
-                              "stopCapture", "()Z");
-    jboolean result = jni()->CallBooleanMethod(*j_capturer_global_, m);
-    CHECK_EXCEPTION(jni()) << "error during VideoCapturerAndroid.stopCapture";
-    DeleteGlobalRef(jni(), j_frame_observer_);
-    return result;
-  }
-
-  std::string GetSupportedFormats() override {
-    jmethodID m =
-        GetMethodID(jni(), *j_video_capturer_class_,
-                    "getSupportedFormatsAsJson", "()Ljava/lang/String;");
-    jstring j_json_caps =
-        (jstring) jni()->CallObjectMethod(*j_capturer_global_, m);
-    CHECK_EXCEPTION(jni()) << "error during supportedFormatsAsJson";
-    return JavaToStdString(jni(), j_json_caps);
-  }
-
- private:
-  JNIEnv* jni() { return AttachCurrentThreadIfNeeded(); }
-
-  const ScopedGlobalRef<jobject> j_capturer_global_;
-  const ScopedGlobalRef<jclass> j_video_capturer_class_;
-  const ScopedGlobalRef<jclass> j_frame_observer_class_;
-  jobject j_frame_observer_;
-
-  static jobject application_context_;
-};
-
-jobject AndroidVideoCapturerJni::application_context_ = nullptr;
-
-JOW(void, VideoCapturerAndroid_00024NativeFrameObserver_nativeOnFrameCaptured)
-    (JNIEnv* jni, jclass, jlong j_capturer, jbyteArray j_frame,
-        jint rotation, jlong ts) {
-  jbyte* bytes = jni->GetByteArrayElements(j_frame, NULL);
-  reinterpret_cast<webrtc::AndroidVideoCapturer*>(
-      j_capturer)->OnIncomingFrame(bytes, jni->GetArrayLength(j_frame),
-                                   rotation, ts);
-  jni->ReleaseByteArrayElements(j_frame, bytes, JNI_ABORT);
-}
-
-JOW(void, VideoCapturerAndroid_00024NativeFrameObserver_nativeCapturerStarted)
-    (JNIEnv* jni, jclass, jlong j_capturer, jboolean j_success) {
-  reinterpret_cast<webrtc::AndroidVideoCapturer*>(
-      j_capturer)->OnCapturerStarted(j_success);
-}
-
 #endif  // #if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
 
-}  // anonymous namespace
-
 static DataChannelInterface* ExtractNativeDC(JNIEnv* jni, jobject j_dc) {
   jfieldID native_dc_id = GetFieldID(jni,
       GetObjectClass(jni, j_dc), "nativeDataChannel", "J");
@@ -2923,16 +2441,15 @@
     JNIEnv* jni, jclass, jobject context,
     jboolean initialize_audio, jboolean initialize_video,
     jboolean vp8_hw_acceleration, jobject render_egl_context) {
-  CHECK(g_jvm) << "JNI_OnLoad failed to run?";
   bool failure = false;
   vp8_hw_acceleration_enabled = vp8_hw_acceleration;
   if (!factory_static_initialized) {
     if (initialize_video) {
-      failure |= webrtc::SetRenderAndroidVM(g_jvm);
+      failure |= webrtc::SetRenderAndroidVM(GetJVM());
       failure |= AndroidVideoCapturerJni::SetAndroidObjects(jni, context);
     }
     if (initialize_audio)
-      failure |= webrtc::VoiceEngine::SetAndroidObjects(g_jvm, jni, context);
+      failure |= webrtc::VoiceEngine::SetAndroidObjects(GetJVM(), jni, context);
     factory_static_initialized = true;
   }
   if (initialize_video) {
@@ -2953,7 +2470,7 @@
     field_trials_init_string = new char[init_string_length + 1];
     rtc::strcpyn(field_trials_init_string, init_string_length + 1, init_string);
     jni->ReleaseStringUTFChars(j_trials_init_string, init_string);
-    LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string ;
+    LOG(LS_INFO) << "initializeFieldTrials: " << field_trials_init_string;
   }
   webrtc::field_trial::InitFieldTrialsFromString(field_trials_init_string);
 }
@@ -3505,3 +3022,5 @@
   reinterpret_cast<VideoTrackInterface*>(j_video_track_pointer)->RemoveRenderer(
       reinterpret_cast<VideoRendererInterface*>(j_renderer_pointer));
 }
+
+}  // namespace webrtc_jni
diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp
index 38260fb..3f0f6a9 100755
--- a/talk/libjingle.gyp
+++ b/talk/libjingle.gyp
@@ -50,7 +50,11 @@
             '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
           ],
           'sources': [
-            'app/webrtc/java/jni/peerconnection_jni.cc'
+            'app/webrtc/java/jni/classreferenceholder.cc',
+            'app/webrtc/java/jni/classreferenceholder.h',
+            'app/webrtc/java/jni/jni_helpers.cc',
+            'app/webrtc/java/jni/jni_helpers.h',
+            'app/webrtc/java/jni/peerconnection_jni.cc',
           ],
           'include_dirs': [
             '<(DEPTH)/third_party/libyuv/include',
@@ -71,6 +75,12 @@
                 ],
               },
             }],
+            ['OS=="android"', {
+              'sources': [
+                'app/webrtc/java/jni/androidvideocapturer_jni.cc',
+                'app/webrtc/java/jni/androidvideocapturer_jni.h',
+              ]
+            }],
           ],
         },
         {