1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1187c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/android/device_info_android.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include <algorithm>
1481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include <sstream>
1581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include <vector>
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include "json/json.h"
1881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include "third_party/icu/source/common/unicode/unistr.h"
1987c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/android/video_capture_android.h"
2081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
2187c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/ref_count.h"
2287c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h"
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
24b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.orgnamespace webrtc {
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
26b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.orgnamespace videocapturemodule {
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
28b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org// Helper for storing lists of pairs of ints.  Used e.g. for resolutions & FPS
29b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org// ranges.
30b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.orgtypedef std::pair<int, int> IntPair;
31b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.orgtypedef std::vector<IntPair> IntPairs;
32b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org
33b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.orgstatic std::string IntPairsToString(const IntPairs& pairs, char separator) {
3481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  std::stringstream stream;
3581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  for (size_t i = 0; i < pairs.size(); ++i) {
3681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    if (i > 0)
3781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      stream << ", ";
38b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org    stream << "(" << pairs[i].first << separator << pairs[i].second << ")";
3981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  }
4081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return stream.str();
4159b3a4ca1db1bb16568f4d184c7cd13e9c1f5786fischman@webrtc.org}
4259b3a4ca1db1bb16568f4d184c7cd13e9c1f5786fischman@webrtc.org
4381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgstruct AndroidCameraInfo {
4481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  std::string name;
4581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  bool front_facing;
4681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  int orientation;
47b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org  IntPairs resolutions;  // Pairs are: (width,height).
48b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org  // Pairs are (min,max) in units of FPS*1000 ("milli-frame-per-second").
49b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org  IntPairs mfpsRanges;
5081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
5181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  std::string ToString() {
5281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    std::stringstream stream;
53b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org    stream << "Name: [" << name << "], MFPS ranges: ["
54b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org           << IntPairsToString(mfpsRanges, ':')
5581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org           << "], front_facing: " << front_facing
5681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org           << ", orientation: " << orientation << ", resolutions: ["
57b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org           << IntPairsToString(resolutions, 'x') << "]";
5881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    return stream.str();
5981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  }
6081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org};
6181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
6281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// Camera info; populated during DeviceInfoAndroid::Initialize() and immutable
6381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// thereafter.
6481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgstatic std::vector<AndroidCameraInfo>* g_camera_info = NULL;
6581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
6681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// Set |*index| to the index of |name| in g_camera_info or return false if no
6781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// match found.
6881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgstatic bool FindCameraIndexByName(const std::string& name, size_t* index) {
6981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  for (size_t i = 0; i < g_camera_info->size(); ++i) {
7081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    if (g_camera_info->at(i).name == name) {
7181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      *index = i;
7281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      return true;
7381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    }
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
7581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return false;
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
7881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// Returns a pointer to the named member of g_camera_info, or NULL if no match
7981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// is found.
8081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgstatic AndroidCameraInfo* FindCameraInfoByName(const std::string& name) {
8181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  size_t index = 0;
8281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (FindCameraIndexByName(name, &index))
8381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    return &g_camera_info->at(index);
8481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return NULL;
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
8781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org// static
8881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgvoid DeviceInfoAndroid::Initialize(JNIEnv* jni) {
8981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  // TODO(henrike): this "if" would make a lot more sense as an assert, but
9081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  // Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_GetVideoEngine() and
9181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  // Java_org_webrtc_videoengineapp_ViEAndroidJavaAPI_Terminate() conspire to
9281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  // prevent this.  Once that code is made to only
9381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  // VideoEngine::SetAndroidObjects() once per process, this can turn into an
9481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  // assert.
9581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (g_camera_info)
9681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    return;
9781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
9881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  g_camera_info = new std::vector<AndroidCameraInfo>();
9981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jclass j_info_class =
10081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      jni->FindClass("org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid");
10181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  assert(j_info_class);
10281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jmethodID j_initialize = jni->GetStaticMethodID(
10381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      j_info_class, "getDeviceInfo", "()Ljava/lang/String;");
10481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jstring j_json_info = static_cast<jstring>(
10581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      jni->CallStaticObjectMethod(j_info_class, j_initialize));
10681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
10781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  const jchar* jchars = jni->GetStringChars(j_json_info, NULL);
10881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  icu::UnicodeString ustr(jchars, jni->GetStringLength(j_json_info));
10981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  jni->ReleaseStringChars(j_json_info, jchars);
11081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  std::string json_info;
11181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  ustr.toUTF8String(json_info);
11281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
11381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  Json::Value cameras;
11481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  Json::Reader reader(Json::Features::strictMode());
11581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  bool parsed = reader.parse(json_info, cameras);
11681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (!parsed) {
11781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    std::stringstream stream;
11881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    stream << "Failed to parse configuration:\n"
11981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org           << reader.getFormattedErrorMessages();
12081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    assert(false);
12181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    return;
12281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  }
12381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  for (Json::ArrayIndex i = 0; i < cameras.size(); ++i) {
12481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    const Json::Value& camera = cameras[i];
12581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    AndroidCameraInfo info;
12681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    info.name = camera["name"].asString();
12781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    info.front_facing = camera["front_facing"].asBool();
12881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    info.orientation = camera["orientation"].asInt();
12981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    Json::Value sizes = camera["sizes"];
13081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    for (Json::ArrayIndex j = 0; j < sizes.size(); ++j) {
13181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      const Json::Value& size = sizes[j];
13281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      info.resolutions.push_back(std::make_pair(
13381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org          size["width"].asInt(), size["height"].asInt()));
13481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    }
135b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org    Json::Value mfpsRanges = camera["mfpsRanges"];
136b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org    for (Json::ArrayIndex j = 0; j < mfpsRanges.size(); ++j) {
137b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      const Json::Value& mfpsRange = mfpsRanges[j];
138b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      info.mfpsRanges.push_back(std::make_pair(mfpsRange["min_mfps"].asInt(),
139b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org                                               mfpsRange["max_mfps"].asInt()));
140b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org    }
14181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    g_camera_info->push_back(info);
14281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  }
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
145ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.orgvoid DeviceInfoAndroid::DeInitialize() {
146ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org  if (g_camera_info) {
147ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    delete g_camera_info;
148ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org    g_camera_info = NULL;
149ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org  }
150ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org}
151ca2c70f2bae88987267a2727449ac86330fb8dbdbraveyao@webrtc.org
15281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgVideoCaptureModule::DeviceInfo* VideoCaptureImpl::CreateDeviceInfo(
15381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    const int32_t id) {
15481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return new videocapturemodule::DeviceInfoAndroid(id);
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
15781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgDeviceInfoAndroid::DeviceInfoAndroid(const int32_t id) :
15881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    DeviceInfoImpl(id) {
15981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org}
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
16181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgDeviceInfoAndroid::~DeviceInfoAndroid() {
16281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org}
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
16481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgbool DeviceInfoAndroid::FindCameraIndex(const char* deviceUniqueIdUTF8,
16581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org                                        size_t* index) {
16681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return FindCameraIndexByName(deviceUniqueIdUTF8, index);
16781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org}
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
16981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orgint32_t DeviceInfoAndroid::Init() {
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
17381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.orguint32_t DeviceInfoAndroid::NumberOfDevices() {
17481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return g_camera_info->size();
17581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org}
17681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org
177f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t DeviceInfoAndroid::GetDeviceName(
178f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org    uint32_t deviceNumber,
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    char* deviceNameUTF8,
180f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org    uint32_t deviceNameLength,
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    char* deviceUniqueIdUTF8,
182f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org    uint32_t deviceUniqueIdUTF8Length,
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    char* /*productUniqueIdUTF8*/,
184f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org    uint32_t /*productUniqueIdUTF8Length*/) {
18581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (deviceNumber >= g_camera_info->size())
18681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    return -1;
18781cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  const AndroidCameraInfo& info = g_camera_info->at(deviceNumber);
18881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (info.name.length() + 1 > deviceNameLength ||
18981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      info.name.length() + 1 > deviceUniqueIdUTF8Length) {
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
19281cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  memcpy(deviceNameUTF8, info.name.c_str(), info.name.length() + 1);
19381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  memcpy(deviceUniqueIdUTF8, info.name.c_str(), info.name.length() + 1);
19481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return 0;
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
197f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t DeviceInfoAndroid::CreateCapabilityMap(
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const char* deviceUniqueIdUTF8) {
19952c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org  _captureCapabilities.clear();
20081cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  const AndroidCameraInfo* info = FindCameraInfoByName(deviceUniqueIdUTF8);
20181cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (info == NULL)
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
20481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  for (size_t i = 0; i < info->resolutions.size(); ++i) {
205b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org    for (size_t j = 0; j < info->mfpsRanges.size(); ++j) {
206b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      const IntPair& size = info->resolutions[i];
207b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      const IntPair& mfpsRange = info->mfpsRanges[j];
208b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      VideoCaptureCapability cap;
209b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      cap.width = size.first;
210b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      cap.height = size.second;
211b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      cap.maxFPS = mfpsRange.second / 1000;
212b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      cap.expectedCaptureDelay = kExpectedCaptureDelay;
213b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      cap.rawType = kVideoNV21;
214b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      _captureCapabilities.push_back(cap);
215b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org    }
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
21752c5c708de6f5bcf9c2a58cece45013aa5efacd7pbos@webrtc.org  return _captureCapabilities.size();
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
220f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t DeviceInfoAndroid::GetOrientation(
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const char* deviceUniqueIdUTF8,
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    VideoCaptureRotation& orientation) {
22381cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  const AndroidCameraInfo* info = FindCameraInfoByName(deviceUniqueIdUTF8);
22481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (info == NULL ||
22581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org      !VideoCaptureImpl::RotationFromDegrees(info->orientation, &orientation)) {
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
22881cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  return 0;
22981cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org}
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
231b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.orgvoid DeviceInfoAndroid::GetMFpsRange(const char* deviceUniqueIdUTF8,
232b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org                                     int max_fps_to_match,
233b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org                                     int* min_mfps, int* max_mfps) {
23481cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  const AndroidCameraInfo* info = FindCameraInfoByName(deviceUniqueIdUTF8);
23581cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org  if (info == NULL)
23681cd5ca677e30076888b865dc28b35ed293bb4bcfischman@webrtc.org    return;
2372a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org  int desired_mfps = max_fps_to_match * 1000;
2382a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org  int best_diff_mfps = 0;
2392a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org  LOG(LS_INFO) << "Search for best target mfps " << desired_mfps;
2402a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org  // Search for best fps range with preference shifted to constant fps modes.
241b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org  for (size_t i = 0; i < info->mfpsRanges.size(); ++i) {
2422a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org    int diff_mfps = abs(info->mfpsRanges[i].first - desired_mfps) +
2432a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org        abs(info->mfpsRanges[i].second - desired_mfps) +
2442a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org        (info->mfpsRanges[i].second - info->mfpsRanges[i].first) / 2;
2452a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org    LOG(LS_INFO) << "Fps range " << info->mfpsRanges[i].first << ":" <<
2462a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org        info->mfpsRanges[i].second << ". Distance: " << diff_mfps;
2472a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org    if (i == 0 || diff_mfps < best_diff_mfps) {
2482a1d25c7eb3a19e7f1fee359e75a03b5313481c9glaznev@webrtc.org      best_diff_mfps = diff_mfps;
249b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      *min_mfps = info->mfpsRanges[i].first;
250b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org      *max_mfps = info->mfpsRanges[i].second;
251b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org    }
252b515322d1022f91bb98ed57b47749076db8218adfischman@webrtc.org  }
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace videocapturemodule
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
257