VideoCapturerAndroid: Add possibility to request a new resolution from the video adapter.

BUG=
R=glaznev@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#9434}
diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java
index e4141f0..657e94c 100644
--- a/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java
+++ b/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java
@@ -92,6 +92,9 @@
       }
     }
 
+    @Override
+    public void OnOutputFormatRequest(int width, int height, int fps) {}
+
     public boolean WaitForCapturerToStart() throws InterruptedException {
       synchronized (capturerStartLock) {
         capturerStartLock.wait();
diff --git a/talk/app/webrtc/androidvideocapturer.cc b/talk/app/webrtc/androidvideocapturer.cc
index 2c9c031..65f883e 100644
--- a/talk/app/webrtc/androidvideocapturer.cc
+++ b/talk/app/webrtc/androidvideocapturer.cc
@@ -242,4 +242,13 @@
   SignalFrameCaptured(this, frame_factory_->GetCapturedFrame());
 }
 
+void AndroidVideoCapturer::OnOutputFormatRequest(
+    int width, int height, int fps) {
+  CHECK(thread_checker_.CalledOnValidThread());
+  const cricket::VideoFormat& current = video_adapter()->output_format();
+  cricket::VideoFormat format(
+      width, height, cricket::VideoFormat::FpsToInterval(fps), current.fourcc);
+  video_adapter()->OnOutputFormatRequest(format);
+}
+
 }  // namespace webrtc
diff --git a/talk/app/webrtc/androidvideocapturer.h b/talk/app/webrtc/androidvideocapturer.h
index 2dffb9c..2cfbdd8 100644
--- a/talk/app/webrtc/androidvideocapturer.h
+++ b/talk/app/webrtc/androidvideocapturer.h
@@ -74,6 +74,9 @@
                        int rotation,
                        int64 time_stamp);
 
+  // Called from JNI to request a new video format.
+  void OnOutputFormatRequest(int width, int height, int fps);
+
   AndroidVideoCapturerDelegate* delegate() { return delegate_.get(); }
 
  private:
diff --git a/talk/app/webrtc/java/jni/androidvideocapturer_jni.cc b/talk/app/webrtc/java/jni/androidvideocapturer_jni.cc
index 1fcf635..3f3b7a6 100644
--- a/talk/app/webrtc/java/jni/androidvideocapturer_jni.cc
+++ b/talk/app/webrtc/java/jni/androidvideocapturer_jni.cc
@@ -182,6 +182,15 @@
                 this, video_frame, length, rotation, time_stamp));
 }
 
+void AndroidVideoCapturerJni::OnOutputFormatRequest(int width,
+                                                    int height,
+                                                    int fps) {
+  invoker_.AsyncInvoke<void>(
+      thread_,
+      rtc::Bind(&AndroidVideoCapturerJni::OnOutputFormatRequest_w,
+                this, width, height, fps));
+}
+
 void AndroidVideoCapturerJni::OnCapturerStarted_w(bool success) {
   CHECK(thread_checker_.CalledOnValidThread());
   if (capturer_) {
@@ -206,6 +215,17 @@
   }
 }
 
+void AndroidVideoCapturerJni::OnOutputFormatRequest_w(int width,
+                                                      int height,
+                                                      int fps) {
+  CHECK(thread_checker_.CalledOnValidThread());
+  if (capturer_) {
+    capturer_->OnOutputFormatRequest(width, height, fps);
+  } else {
+    LOG(LS_WARNING) << "OnOutputFormatRequest_w is called for closed capturer.";
+  }
+}
+
 JNIEnv* AndroidVideoCapturerJni::jni() { return AttachCurrentThreadIfNeeded(); }
 
 JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnFrameCaptured)
@@ -233,5 +253,13 @@
       j_success);
 }
 
+JOW(void, VideoCapturerAndroid_00024NativeObserver_nativeOnOutputFormatRequest)
+    (JNIEnv* jni, jclass, jlong j_capturer, jint j_width, jint j_height,
+        jint j_fps) {
+  LOG(LS_INFO) << "NativeObserver_nativeOnOutputFormatRequest";
+  reinterpret_cast<AndroidVideoCapturerJni*>(j_capturer)->OnOutputFormatRequest(
+      j_width, j_height, j_fps);
+}
+
 }  // namespace webrtc_jni
 
diff --git a/talk/app/webrtc/java/jni/androidvideocapturer_jni.h b/talk/app/webrtc/java/jni/androidvideocapturer_jni.h
index 1e3ace2..2747ac6 100644
--- a/talk/app/webrtc/java/jni/androidvideocapturer_jni.h
+++ b/talk/app/webrtc/java/jni/androidvideocapturer_jni.h
@@ -66,6 +66,7 @@
                        int length,
                        int rotation,
                        int64 time_stamp);
+  void OnOutputFormatRequest(int width, int height, int fps);
 protected:
   AndroidVideoCapturerJni(JNIEnv* jni, jobject j_video_capturer);
   ~AndroidVideoCapturerJni();
@@ -79,6 +80,7 @@
                          int length,
                          int rotation,
                          int64 time_stamp);
+  void OnOutputFormatRequest_w(int width, int height, int fps);
   void ReturnBuffer_w(int64 time_stamp);
 
   JNIEnv* jni();
diff --git a/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java b/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java
index e40cd1a..63388a2 100644
--- a/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java
+++ b/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java
@@ -270,6 +270,21 @@
     return true;
   }
 
+  // Requests a new output format from the video capturer. Captured frames
+  // by the camera will be scaled/or dropped by the video capturer.
+  public synchronized void onOutputFormatRequest(
+      final int width, final int height, final int fps) {
+    if (cameraThreadHandler == null) {
+      Log.e(TAG, "Calling onOutputFormatRequest() for already stopped camera.");
+      return;
+    }
+    cameraThreadHandler.post(new Runnable() {
+      @Override public void run() {
+        onOutputFormatRequestOnCameraThread(width, height, fps);
+      }
+    });
+  }
+
   private VideoCapturerAndroid() {
     Log.d(TAG, "VideoCapturerAndroid");
   }
@@ -641,6 +656,16 @@
     }
   }
 
+  private void onOutputFormatRequestOnCameraThread(
+      int width, int height, int fps) {
+    if (camera == null) {
+      return;
+    }
+    Log.d(TAG, "onOutputFormatRequestOnCameraThread: " + width + "x" + height +
+        "@" + fps);
+    frameObserver.OnOutputFormatRequest(width, height, fps);
+  }
+
   synchronized void returnBuffer(final long timeStamp) {
     if (cameraThreadHandler == null) {
       // The camera has been stopped.
@@ -919,6 +944,11 @@
     // VideoCapturerAndroid.
     abstract void OnFrameCaptured(byte[] data, int length, 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 fps);
   }
 
   // An implementation of CapturerObserver that forwards all calls from
@@ -941,9 +971,16 @@
       nativeOnFrameCaptured(nativeCapturer, data, length, rotation, timeStamp);
     }
 
+    @Override
+    public void OnOutputFormatRequest(int width, int height, int fps) {
+      nativeOnOutputFormatRequest(nativeCapturer, width, height, fps);
+    }
+
     private native void nativeCapturerStarted(long nativeCapturer,
         boolean success);
     private native void nativeOnFrameCaptured(long nativeCapturer,
         byte[] data, int length, int rotation, long timeStamp);
+    private native void nativeOnOutputFormatRequest(long nativeCapturer,
+        int width, int height, int fps);
   }
 }