diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java index 5c700ef635..54f77c5166 100644 --- a/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java +++ b/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java @@ -30,7 +30,7 @@ import android.hardware.Camera; import android.test.ActivityTestCase; import android.test.suitebuilder.annotation.SmallTest; -import org.webrtc.VideoCapturerAndroid.CaptureFormat; +import org.webrtc.CameraEnumerationAndroid.CaptureFormat; import org.webrtc.VideoRenderer.I420Frame; import java.util.ArrayList; @@ -173,7 +173,7 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { // to a Java video renderer using the front facing video capturer. // It tests both the Java and the C++ layer. public void testStartFrontFacingVideoCapturer() throws Exception { - starCapturerAndRender(VideoCapturerAndroid.getNameOfFrontFacingDevice()); + starCapturerAndRender(CameraEnumerationAndroid.getNameOfFrontFacingDevice()); } @SmallTest @@ -184,7 +184,7 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { if (!HaveTwoCameras()) { return; } - starCapturerAndRender(VideoCapturerAndroid.getNameOfBackFacingDevice()); + starCapturerAndRender(CameraEnumerationAndroid.getNameOfBackFacingDevice()); } @SmallTest @@ -246,14 +246,14 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { public void testStartStopWithDifferentResolutions() throws Exception { FakeCapturerObserver observer = new FakeCapturerObserver(); - String deviceName = VideoCapturerAndroid.getDeviceName(0); + String deviceName = CameraEnumerationAndroid.getDeviceName(0); ArrayList formats = - VideoCapturerAndroid.getSupportedFormats(0); + CameraEnumerationAndroid.getSupportedFormats(0); VideoCapturerAndroid capturer = VideoCapturerAndroid.create(deviceName, null); for(int i = 0; i < 3 ; ++i) { - VideoCapturerAndroid.CaptureFormat format = formats.get(i); + CameraEnumerationAndroid.CaptureFormat format = formats.get(i); capturer.startCapture(format.width, format.height, format.maxFramerate, getInstrumentation().getContext(), observer); assertTrue(observer.WaitForCapturerToStart()); @@ -271,13 +271,13 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { public void testReturnBufferLate() throws Exception { FakeCapturerObserver observer = new FakeCapturerObserver(); - String deviceName = VideoCapturerAndroid.getDeviceName(0); + String deviceName = CameraEnumerationAndroid.getDeviceName(0); ArrayList formats = - VideoCapturerAndroid.getSupportedFormats(0); + CameraEnumerationAndroid.getSupportedFormats(0); VideoCapturerAndroid capturer = VideoCapturerAndroid.create(deviceName, null); - VideoCapturerAndroid.CaptureFormat format = formats.get(0); + CameraEnumerationAndroid.CaptureFormat format = formats.get(0); capturer.startCapture(format.width, format.height, format.maxFramerate, getInstrumentation().getContext(), observer); assertTrue(observer.WaitForCapturerToStart()); diff --git a/talk/app/webrtc/java/android/org/webrtc/CameraEnumerationAndroid.java b/talk/app/webrtc/java/android/org/webrtc/CameraEnumerationAndroid.java new file mode 100644 index 0000000000..d6fa1274e4 --- /dev/null +++ b/talk/app/webrtc/java/android/org/webrtc/CameraEnumerationAndroid.java @@ -0,0 +1,293 @@ +/* + * 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. + */ + +package org.webrtc; + +import static java.lang.Math.abs; +import static java.lang.Math.ceil; + +import android.hardware.Camera; +import android.util.Log; +import android.graphics.ImageFormat; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +@SuppressWarnings("deprecation") +public class CameraEnumerationAndroid { + private final static String TAG = "CameraEnumerationAndroid"; + // List of formats supported by all cameras. This list is filled once in order + // to be able to switch cameras. + public static List> supportedFormats; + + public static class CaptureFormat { + public final int width; + 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 + // all imageFormats. + public final int imageFormat = ImageFormat.YV12; + + public CaptureFormat(int width, int height, int minFramerate, + int maxFramerate) { + this.width = width; + this.height = height; + this.minFramerate = minFramerate; + this.maxFramerate = maxFramerate; + } + + // Calculates the frame size of this capture format. + public int frameSize() { + return frameSize(width, height, imageFormat); + } + + // Calculates the frame size of the specified image format. Currently only + // supporting ImageFormat.YV12. The YV12's stride is the closest rounded up + // multiple of 16 of the width and width and height are always even. + // Android guarantees this: + // http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFormat%28int%29 + public static int frameSize(int width, int height, int imageFormat) { + if (imageFormat != ImageFormat.YV12) { + throw new UnsupportedOperationException("Don't know how to calculate " + + "the frame size of non-YV12 image formats."); + } + int yStride = roundUp(width, 16); + int uvStride = roundUp(yStride / 2, 16); + int ySize = yStride * height; + int uvSize = uvStride * height / 2; + return ySize + uvSize * 2; + } + + // Rounds up |x| to the closest value that is a multiple of |alignment|. + private static int roundUp(int x, int alignment) { + return (int)ceil(x / (double)alignment) * alignment; + } + + @Override + public String toString() { + return width + "x" + height + "@[" + minFramerate + ":" + maxFramerate + "]"; + } + + @Override + public boolean equals(Object that) { + if (!(that instanceof CaptureFormat)) { + return false; + } + final CaptureFormat c = (CaptureFormat) that; + return width == c.width && height == c.height && maxFramerate == c.maxFramerate + && minFramerate == c.minFramerate; + } + } + + // Returns device names that can be used to create a new VideoCapturerAndroid. + public static String[] getDeviceNames() { + String[] names = new String[Camera.getNumberOfCameras()]; + for (int i = 0; i < Camera.getNumberOfCameras(); ++i) { + names[i] = getDeviceName(i); + } + return names; + } + + // Returns number of cameras on device. + public static int getDeviceCount() { + return Camera.getNumberOfCameras(); + } + + // Returns the name of the camera with camera index. Returns null if the + // camera can not be used. + public static String getDeviceName(int index) { + Camera.CameraInfo info = new Camera.CameraInfo(); + try { + Camera.getCameraInfo(index, info); + } catch (Exception e) { + Log.e(TAG, "getCameraInfo failed on index " + index,e); + return null; + } + + String facing = + (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) ? "front" : "back"; + return "Camera " + index + ", Facing " + facing + + ", Orientation " + info.orientation; + } + + // Returns the name of the front facing camera. Returns null if the + // camera can not be used or does not exist. + public static String getNameOfFrontFacingDevice() { + for (int i = 0; i < Camera.getNumberOfCameras(); ++i) { + Camera.CameraInfo info = new Camera.CameraInfo(); + try { + Camera.getCameraInfo(i, info); + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) + return getDeviceName(i); + } catch (Exception e) { + Log.e(TAG, "getCameraInfo failed on index " + i, e); + } + } + return null; + } + + // Returns the name of the back facing camera. Returns null if the + // camera can not be used or does not exist. + public static String getNameOfBackFacingDevice() { + for (int i = 0; i < Camera.getNumberOfCameras(); ++i) { + Camera.CameraInfo info = new Camera.CameraInfo(); + try { + Camera.getCameraInfo(i, info); + if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) + return getDeviceName(i); + } catch (Exception e) { + Log.e(TAG, "getCameraInfo failed on index " + i, e); + } + } + return null; + } + + public static boolean initStatics() { + if (supportedFormats != null) + return true; + try { + Log.d(TAG, "Get supported formats."); + supportedFormats = + new ArrayList>(Camera.getNumberOfCameras()); + // Start requesting supported formats from camera with the highest index + // (back camera) first. If it fails then likely camera is in bad state. + for (int i = Camera.getNumberOfCameras() - 1; i >= 0; i--) { + ArrayList supportedFormat = getSupportedFormats(i); + if (supportedFormat.size() == 0) { + Log.e(TAG, "Fail to get supported formats for camera " + i); + supportedFormats = null; + return false; + } + supportedFormats.add(supportedFormat); + } + // Reverse the list since it is filled in reverse order. + Collections.reverse(supportedFormats); + Log.d(TAG, "Get supported formats done."); + return true; + } catch (Exception e) { + supportedFormats = null; + Log.e(TAG, "InitStatics failed",e); + } + return false; + } + + public static String getSupportedFormatsAsJson(int id) throws JSONException { + List formats = supportedFormats.get(id); + JSONArray json_formats = new JSONArray(); + for (CaptureFormat format : formats) { + JSONObject json_format = new JSONObject(); + json_format.put("width", format.width); + json_format.put("height", format.height); + json_format.put("framerate", (format.maxFramerate + 999) / 1000); + json_formats.put(json_format); + } + Log.d(TAG, "Supported formats for camera " + id + ": " + + json_formats.toString(2)); + return json_formats.toString(); + } + + // Returns a list of CaptureFormat for the camera with index id. + public static ArrayList getSupportedFormats(int id) { + ArrayList formatList = new ArrayList(); + + Camera camera; + try { + Log.d(TAG, "Opening camera " + id); + camera = Camera.open(id); + } catch (Exception e) { + Log.e(TAG, "Open camera failed on id " + id, e); + return formatList; + } + + try { + Camera.Parameters parameters; + parameters = camera.getParameters(); + // getSupportedPreviewFpsRange returns a sorted list. + List listFpsRange = parameters.getSupportedPreviewFpsRange(); + int[] range = {0, 0}; + if (listFpsRange != null) + range = listFpsRange.get(listFpsRange.size() -1); + + List supportedSizes = parameters.getSupportedPreviewSizes(); + for (Camera.Size size : supportedSizes) { + formatList.add(new CaptureFormat(size.width, size.height, + range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], + range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX])); + } + } catch (Exception e) { + Log.e(TAG, "getSupportedFormats failed on id " + id, e); + } + camera.release(); + camera = null; + return formatList; + } + + // Helper class for finding the closest supported format for the two functions below. + private static abstract class ClosestComparator implements Comparator { + // Difference between supported and requested parameter. + abstract int diff(T supportedParameter); + + @Override + public int compare(T t1, T t2) { + return diff(t1) - diff(t2); + } + } + + public static int[] getFramerateRange(Camera.Parameters parameters, final int framerate) { + List listFpsRange = parameters.getSupportedPreviewFpsRange(); + if (listFpsRange.isEmpty()) { + Log.w(TAG, "No supported preview fps range"); + return new int[]{0, 0}; + } + return Collections.min(listFpsRange, + new ClosestComparator() { + @Override int diff(int[] range) { + return abs(framerate - range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]) + + abs(framerate - range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]); + } + }); + } + + public static Camera.Size getClosestSupportedSize( + List supportedSizes, final int requestedWidth, final int requestedHeight) { + return Collections.min(supportedSizes, + new ClosestComparator() { + @Override int diff(Camera.Size size) { + return abs(requestedWidth - size.width) + abs(requestedHeight - size.height); + } + }); + } +} diff --git a/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java b/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java similarity index 74% rename from talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java rename to talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java index ac42883e98..00034fc143 100644 --- a/talk/app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java +++ b/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java @@ -27,11 +27,7 @@ package org.webrtc; -import static java.lang.Math.abs; -import static java.lang.Math.ceil; - import android.content.Context; -import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.hardware.Camera.PreviewCallback; @@ -44,15 +40,13 @@ import android.util.Log; import android.view.Surface; import android.view.WindowManager; -import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; + +import org.webrtc.CameraEnumerationAndroid.CaptureFormat; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; @@ -100,9 +94,6 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba private volatile boolean pendingCameraSwitch; private CapturerObserver frameObserver = null; private CameraErrorHandler errorHandler = null; - // List of formats supported by all cameras. This list is filled once in order - // to be able to switch cameras. - private static List> supportedFormats; // Camera error callback. private final Camera.ErrorCallback cameraErrorCallback = @@ -158,69 +149,6 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba public void onCameraError(String errorDescription); } - // Returns device names that can be used to create a new VideoCapturerAndroid. - public static String[] getDeviceNames() { - String[] names = new String[Camera.getNumberOfCameras()]; - for (int i = 0; i < Camera.getNumberOfCameras(); ++i) { - names[i] = getDeviceName(i); - } - return names; - } - - // Returns number of cameras on device. - public static int getDeviceCount() { - return Camera.getNumberOfCameras(); - } - - // Returns the name of the camera with camera index. Returns null if the - // camera can not be used. - public static String getDeviceName(int index) { - Camera.CameraInfo info = new Camera.CameraInfo(); - try { - Camera.getCameraInfo(index, info); - } catch (Exception e) { - Log.e(TAG, "getCameraInfo failed on index " + index,e); - return null; - } - - String facing = - (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) ? "front" : "back"; - return "Camera " + index + ", Facing " + facing - + ", Orientation " + info.orientation; - } - - // Returns the name of the front facing camera. Returns null if the - // camera can not be used or does not exist. - public static String getNameOfFrontFacingDevice() { - for (int i = 0; i < Camera.getNumberOfCameras(); ++i) { - Camera.CameraInfo info = new Camera.CameraInfo(); - try { - Camera.getCameraInfo(i, info); - if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) - return getDeviceName(i); - } catch (Exception e) { - Log.e(TAG, "getCameraInfo failed on index " + i, e); - } - } - return null; - } - - // Returns the name of the back facing camera. Returns null if the - // camera can not be used or does not exist. - public static String getNameOfBackFacingDevice() { - for (int i = 0; i < Camera.getNumberOfCameras(); ++i) { - Camera.CameraInfo info = new Camera.CameraInfo(); - try { - Camera.getCameraInfo(i, info); - if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) - return getDeviceName(i); - } catch (Exception e) { - Log.e(TAG, "getCameraInfo failed on index " + i, e); - } - } - return null; - } - public static VideoCapturerAndroid create(String name, CameraErrorHandler errorHandler) { VideoCapturer capturer = VideoCapturer.create(name); @@ -292,7 +220,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba } public synchronized List getSupportedFormats() { - return supportedFormats.get(id); + return CameraEnumerationAndroid.supportedFormats.get(id); } private VideoCapturerAndroid() { @@ -307,7 +235,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba // compatible with the generic VideoCapturer class. synchronized boolean init(String deviceName) { Log.d(TAG, "init: " + deviceName); - if (deviceName == null || !initStatics()) + if (deviceName == null || !CameraEnumerationAndroid.initStatics()) return false; boolean foundDevice = false; @@ -316,7 +244,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba foundDevice = true; } else { for (int i = 0; i < Camera.getNumberOfCameras(); ++i) { - String existing_device = getDeviceName(i); + String existing_device = CameraEnumerationAndroid.getDeviceName(i); if (existing_device != null && deviceName.equals(existing_device)) { this.id = i; foundDevice = true; @@ -326,150 +254,8 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba return foundDevice; } - private static boolean initStatics() { - if (supportedFormats != null) - return true; - try { - Log.d(TAG, "Get supported formats."); - supportedFormats = - new ArrayList>(Camera.getNumberOfCameras()); - // Start requesting supported formats from camera with the highest index - // (back camera) first. If it fails then likely camera is in bad state. - for (int i = Camera.getNumberOfCameras() - 1; i >= 0; i--) { - ArrayList supportedFormat = getSupportedFormats(i); - if (supportedFormat.size() == 0) { - Log.e(TAG, "Fail to get supported formats for camera " + i); - supportedFormats = null; - return false; - } - supportedFormats.add(supportedFormat); - } - // Reverse the list since it is filled in reverse order. - Collections.reverse(supportedFormats); - Log.d(TAG, "Get supported formats done."); - return true; - } catch (Exception e) { - supportedFormats = null; - Log.e(TAG, "InitStatics failed",e); - } - return false; - } - String getSupportedFormatsAsJson() throws JSONException { - return getSupportedFormatsAsJson(id); - } - - public static class CaptureFormat { - public final int width; - 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 - // all imageFormats. - public final int imageFormat = ImageFormat.YV12; - - public CaptureFormat(int width, int height, int minFramerate, - int maxFramerate) { - this.width = width; - this.height = height; - this.minFramerate = minFramerate; - this.maxFramerate = maxFramerate; - } - - // Calculates the frame size of this capture format. - public int frameSize() { - return frameSize(width, height, imageFormat); - } - - // Calculates the frame size of the specified image format. Currently only - // supporting ImageFormat.YV12. The YV12's stride is the closest rounded up - // multiple of 16 of the width and width and height are always even. - // Android guarantees this: - // http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setPreviewFormat%28int%29 - public static int frameSize(int width, int height, int imageFormat) { - if (imageFormat != ImageFormat.YV12) { - throw new UnsupportedOperationException("Don't know how to calculate " - + "the frame size of non-YV12 image formats."); - } - int yStride = roundUp(width, 16); - int uvStride = roundUp(yStride / 2, 16); - int ySize = yStride * height; - int uvSize = uvStride * height / 2; - return ySize + uvSize * 2; - } - - // Rounds up |x| to the closest value that is a multiple of |alignment|. - private static int roundUp(int x, int alignment) { - return (int)ceil(x / (double)alignment) * alignment; - } - - @Override - public String toString() { - return width + "x" + height + "@[" + minFramerate + ":" + maxFramerate + "]"; - } - - @Override - public boolean equals(Object that) { - if (!(that instanceof CaptureFormat)) { - return false; - } - final CaptureFormat c = (CaptureFormat) that; - return width == c.width && height == c.height && maxFramerate == c.maxFramerate - && minFramerate == c.minFramerate; - } - } - - private static String getSupportedFormatsAsJson(int id) throws JSONException { - List formats = supportedFormats.get(id); - JSONArray json_formats = new JSONArray(); - for (CaptureFormat format : formats) { - JSONObject json_format = new JSONObject(); - json_format.put("width", format.width); - json_format.put("height", format.height); - json_format.put("framerate", (format.maxFramerate + 999) / 1000); - json_formats.put(json_format); - } - Log.d(TAG, "Supported formats for camera " + id + ": " - + json_formats.toString(2)); - return json_formats.toString(); - } - - // Returns a list of CaptureFormat for the camera with index id. - static ArrayList getSupportedFormats(int id) { - ArrayList formatList = new ArrayList(); - - Camera camera; - try { - Log.d(TAG, "Opening camera " + id); - camera = Camera.open(id); - } catch (Exception e) { - Log.e(TAG, "Open camera failed on id " + id, e); - return formatList; - } - - try { - Camera.Parameters parameters; - parameters = camera.getParameters(); - // getSupportedPreviewFpsRange returns a sorted list. - List listFpsRange = parameters.getSupportedPreviewFpsRange(); - int[] range = {0, 0}; - if (listFpsRange != null) - range = listFpsRange.get(listFpsRange.size() -1); - - List supportedSizes = parameters.getSupportedPreviewSizes(); - for (Camera.Size size : supportedSizes) { - formatList.add(new CaptureFormat(size.width, size.height, - range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], - range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX])); - } - } catch (Exception e) { - Log.e(TAG, "getSupportedFormats failed on id " + id, e); - } - camera.release(); - camera = null; - return formatList; + return CameraEnumerationAndroid.getSupportedFormatsAsJson(id); } private class CameraThread extends Thread { @@ -597,9 +383,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba // Find closest supported format for |width| x |height| @ |framerate|. final Camera.Parameters parameters = camera.getParameters(); - final int[] range = getFramerateRange(parameters, framerate * 1000); - final Camera.Size previewSize = - getClosestSupportedSize(parameters.getSupportedPreviewSizes(), width, height); + final int[] range = CameraEnumerationAndroid.getFramerateRange(parameters, framerate * 1000); + final Camera.Size previewSize = CameraEnumerationAndroid.getClosestSupportedSize( + parameters.getSupportedPreviewSizes(), width, height); final CaptureFormat captureFormat = new CaptureFormat( previewSize.width, previewSize.height, range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], @@ -625,8 +411,8 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba parameters.setPreviewFormat(captureFormat.imageFormat); // Picture size is for taking pictures and not for preview/video, but we need to set it anyway // as a workaround for an aspect ratio problem on Nexus 7. - final Camera.Size pictureSize = - getClosestSupportedSize(parameters.getSupportedPictureSizes(), width, height); + final Camera.Size pictureSize = CameraEnumerationAndroid.getClosestSupportedSize( + parameters.getSupportedPictureSizes(), width, height); parameters.setPictureSize(pictureSize.width, pictureSize.height); // Temporarily stop preview if it's already running. @@ -747,42 +533,6 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba return orientation; } - // Helper class for finding the closest supported format for the two functions below. - private static abstract class ClosestComparator implements Comparator { - // Difference between supported and requested parameter. - abstract int diff(T supportedParameter); - - @Override - public int compare(T t1, T t2) { - return diff(t1) - diff(t2); - } - } - - private static int[] getFramerateRange(Camera.Parameters parameters, final int framerate) { - List listFpsRange = parameters.getSupportedPreviewFpsRange(); - if (listFpsRange.isEmpty()) { - Log.w(TAG, "No supported preview fps range"); - return new int[]{0, 0}; - } - return Collections.min(listFpsRange, - new ClosestComparator() { - @Override int diff(int[] range) { - return abs(framerate - range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]) - + abs(framerate - range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]); - } - }); - } - - private static Camera.Size getClosestSupportedSize( - List supportedSizes, final int requestedWidth, final int requestedHeight) { - return Collections.min(supportedSizes, - new ClosestComparator() { - @Override int diff(Camera.Size size) { - return abs(requestedWidth - size.width) + abs(requestedHeight - size.height); - } - }); - } - // Called on cameraThread so must not "synchronized". @Override public void onPreviewFrame(byte[] data, Camera callbackCamera) { diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index f268be678f..5a61ca4ee8 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -140,15 +140,16 @@ # included here, or better yet, build a proper .jar in webrtc # and include it here. 'android_java_files': [ + 'app/webrtc/java/android/org/webrtc/CameraEnumerationAndroid.java', 'app/webrtc/java/android/org/webrtc/EglBase.java', 'app/webrtc/java/android/org/webrtc/GlRectDrawer.java', 'app/webrtc/java/android/org/webrtc/GlShader.java', 'app/webrtc/java/android/org/webrtc/GlUtil.java', 'app/webrtc/java/android/org/webrtc/RendererCommon.java', + 'app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java', 'app/webrtc/java/android/org/webrtc/VideoRendererGui.java', - 'app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java', 'app/webrtc/java/src/org/webrtc/MediaCodecVideoDecoder.java', - 'app/webrtc/java/src/org/webrtc/VideoCapturerAndroid.java', + 'app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java', '<(webrtc_modules_dir)/video_render/android/java/src/org/webrtc/videoengine/ViEAndroidGLES20.java', '<(webrtc_modules_dir)/video_render/android/java/src/org/webrtc/videoengine/ViERenderer.java', '<(webrtc_modules_dir)/video_render/android/java/src/org/webrtc/videoengine/ViESurfaceRenderer.java', diff --git a/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java b/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java index e720fe7414..6e54ae2262 100644 --- a/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java +++ b/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java @@ -16,6 +16,7 @@ import android.util.Log; import org.appspot.apprtc.AppRTCClient.SignalingParameters; import org.appspot.apprtc.util.LooperExecutor; +import org.webrtc.CameraEnumerationAndroid; import org.webrtc.DataChannel; import org.webrtc.IceCandidate; import org.webrtc.Logging; @@ -329,7 +330,7 @@ public class PeerConnectionClient { } // Check if there is a camera on device and disable video call if not. - numberOfCameras = VideoCapturerAndroid.getDeviceCount(); + numberOfCameras = CameraEnumerationAndroid.getDeviceCount(); if (numberOfCameras == 0) { Log.w(TAG, "No camera on device. Switch to audio only call."); videoCallEnabled = false; @@ -434,9 +435,9 @@ public class PeerConnectionClient { mediaStream = factory.createLocalMediaStream("ARDAMS"); if (videoCallEnabled) { - String cameraDeviceName = VideoCapturerAndroid.getDeviceName(0); + String cameraDeviceName = CameraEnumerationAndroid.getDeviceName(0); String frontCameraDeviceName = - VideoCapturerAndroid.getNameOfFrontFacingDevice(); + CameraEnumerationAndroid.getNameOfFrontFacingDevice(); if (numberOfCameras > 1 && frontCameraDeviceName != null) { cameraDeviceName = frontCameraDeviceName; }