Allow passing in decoder factory to PeerConnectionFactory.

Bug: webrtc:7760
Change-Id: I8509de8f0170f1f60f917992b5806b926a8bb392
Reviewed-on: https://chromium-review.googlesource.com/535561
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#18787}
diff --git a/webrtc/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/webrtc/sdk/android/api/org/webrtc/PeerConnectionFactory.java
index b70aab0..90b3672 100644
--- a/webrtc/sdk/android/api/org/webrtc/PeerConnectionFactory.java
+++ b/webrtc/sdk/android/api/org/webrtc/PeerConnectionFactory.java
@@ -103,7 +103,12 @@
   // Note: initializeAndroidGlobals must be called at least once before
   // constructing a PeerConnectionFactory.
   public PeerConnectionFactory(Options options) {
-    nativeFactory = nativeCreatePeerConnectionFactory(options);
+    this(options, null /* encoderFactory */, null /* decoderFactory */);
+  }
+
+  public PeerConnectionFactory(
+      Options options, VideoEncoderFactory encoderFactory, VideoDecoderFactory decoderFactory) {
+    nativeFactory = nativeCreatePeerConnectionFactory(options, encoderFactory, decoderFactory);
     if (nativeFactory == 0) {
       throw new RuntimeException("Failed to initialize PeerConnectionFactory!");
     }
@@ -247,7 +252,8 @@
     Logging.d(TAG, "onSignalingThreadReady");
   }
 
-  private static native long nativeCreatePeerConnectionFactory(Options options);
+  private static native long nativeCreatePeerConnectionFactory(
+      Options options, VideoEncoderFactory encoderFactory, VideoDecoderFactory decoderFactory);
 
   private static native long nativeCreateObserver(PeerConnection.Observer observer);
 
diff --git a/webrtc/sdk/android/src/jni/null_video_jni.cc b/webrtc/sdk/android/src/jni/null_video_jni.cc
index 4d8c642..c9a4d16 100644
--- a/webrtc/sdk/android/src/jni/null_video_jni.cc
+++ b/webrtc/sdk/android/src/jni/null_video_jni.cc
@@ -12,11 +12,15 @@
 
 namespace webrtc_jni {
 
-cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory() {
+cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory(
+    JNIEnv* jni,
+    jobject j_encoder_factory) {
   return nullptr;
 }
 
-cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory() {
+cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory(
+    JNIEnv* jni,
+    jobject j_decoder_factory) {
   return nullptr;
 }
 
diff --git a/webrtc/sdk/android/src/jni/peerconnection_jni.cc b/webrtc/sdk/android/src/jni/peerconnection_jni.cc
index fd8a136..4fcfb6e 100644
--- a/webrtc/sdk/android/src/jni/peerconnection_jni.cc
+++ b/webrtc/sdk/android/src/jni/peerconnection_jni.cc
@@ -1121,8 +1121,12 @@
   return native_options;
 }
 
-JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory)(
-    JNIEnv* jni, jclass, jobject joptions) {
+JOW(jlong, PeerConnectionFactory_nativeCreatePeerConnectionFactory)
+(JNIEnv* jni,
+ jclass,
+ jobject joptions,
+ jobject jencoder_factory,
+ jobject jdecoder_factory) {
   // talk/ assumes pretty widely that the current Thread is ThreadManager'd, but
   // ThreadManager only WrapCurrentThread()s the thread where it is first
   // created.  Since the semantics around when auto-wrapping happens in
@@ -1157,8 +1161,8 @@
   }
 
   if (video_hw_acceleration_enabled) {
-    video_encoder_factory = CreateVideoEncoderFactory();
-    video_decoder_factory = CreateVideoDecoderFactory();
+    video_encoder_factory = CreateVideoEncoderFactory(jni, jencoder_factory);
+    video_decoder_factory = CreateVideoDecoderFactory(jni, jdecoder_factory);
   }
   // Do not create network_monitor_factory only if the options are
   // provided and disable_network_monitor therein is set to true.
diff --git a/webrtc/sdk/android/src/jni/video_jni.cc b/webrtc/sdk/android/src/jni/video_jni.cc
index 6097076..616b2e0 100644
--- a/webrtc/sdk/android/src/jni/video_jni.cc
+++ b/webrtc/sdk/android/src/jni/video_jni.cc
@@ -20,15 +20,34 @@
 #include "webrtc/sdk/android/src/jni/classreferenceholder.h"
 #include "webrtc/sdk/android/src/jni/ownedfactoryandthreads.h"
 #include "webrtc/sdk/android/src/jni/surfacetexturehelper_jni.h"
+#include "webrtc/sdk/android/src/jni/videodecoderfactorywrapper.h"
 
 namespace webrtc_jni {
 
-cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory() {
+// TODO(sakal): Remove this once MediaCodecVideoDecoder/Encoder are no longer
+// used and all applications inject their own codecs.
+// This is semi broken if someone wants to create multiple peerconnection
+// factories.
+static MediaCodecVideoDecoderFactory* media_codec_decoder_factory;
+
+cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory(
+    JNIEnv* jni,
+    jobject j_encoder_factory) {
+  RTC_DCHECK(j_encoder_factory == nullptr)
+      << "Injectable video encoders are not supported yet.";
   return new MediaCodecVideoEncoderFactory();
 }
 
-cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory() {
-  return new MediaCodecVideoDecoderFactory();
+cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory(
+    JNIEnv* jni,
+    jobject j_decoder_factory) {
+  if (j_decoder_factory != nullptr) {
+    media_codec_decoder_factory = nullptr;
+    return new VideoDecoderFactoryWrapper(jni, j_decoder_factory);
+  } else {
+    media_codec_decoder_factory = new MediaCodecVideoDecoderFactory();
+    return media_codec_decoder_factory;
+  }
 }
 
 jobject GetJavaSurfaceTextureHelper(
@@ -90,12 +109,9 @@
     encoder_factory->SetEGLContext(jni, local_egl_context);
   }
 
-  MediaCodecVideoDecoderFactory* decoder_factory =
-      static_cast<MediaCodecVideoDecoderFactory*>(
-          owned_factory->decoder_factory());
-  if (decoder_factory) {
+  if (media_codec_decoder_factory) {
     LOG(LS_INFO) << "Set EGL context for HW decoding.";
-    decoder_factory->SetEGLContext(jni, remote_egl_context);
+    media_codec_decoder_factory->SetEGLContext(jni, remote_egl_context);
   }
 }
 
diff --git a/webrtc/sdk/android/src/jni/video_jni.h b/webrtc/sdk/android/src/jni/video_jni.h
index f6ec9e6..c13f33f 100644
--- a/webrtc/sdk/android/src/jni/video_jni.h
+++ b/webrtc/sdk/android/src/jni/video_jni.h
@@ -24,9 +24,13 @@
 
 class SurfaceTextureHelper;
 
-cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory();
+cricket::WebRtcVideoEncoderFactory* CreateVideoEncoderFactory(
+    JNIEnv* jni,
+    jobject j_encoder_factory);
 
-cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory();
+cricket::WebRtcVideoDecoderFactory* CreateVideoDecoderFactory(
+    JNIEnv* jni,
+    jobject j_decoder_factory);
 
 jobject GetJavaSurfaceTextureHelper(
     const rtc::scoped_refptr<SurfaceTextureHelper>& surface_texture_helper);