1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// found in the LICENSE file.
4e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "media/video/capture/android/video_capture_device_factory_android.h"
6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
7e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/android/jni_string.h"
8e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/android/scoped_java_ref.h"
9e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/strings/string_number_conversions.h"
10e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/strings/stringprintf.h"
11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "jni/VideoCaptureFactory_jni.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/video/capture/android/video_capture_device_android.h"
13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochusing base::android::AttachCurrentThread;
15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochusing base::android::ScopedJavaLocalRef;
16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace media {
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// static
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool VideoCaptureDeviceFactoryAndroid::RegisterVideoCaptureDeviceFactory(
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    JNIEnv* env) {
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return RegisterNativesImpl(env);
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//static
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ScopedJavaLocalRef<jobject>
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid(
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int id,
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    jlong nativeVideoCaptureDeviceAndroid) {
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (Java_VideoCaptureFactory_createVideoCapture(
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      AttachCurrentThread(),
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::android::GetApplicationContext(),
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      id,
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      nativeVideoCaptureDeviceAndroid));
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<VideoCaptureDevice> VideoCaptureDeviceFactoryAndroid::Create(
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const VideoCaptureDevice::Name& device_name) {
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int id;
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!base::StringToInt(device_name.id(), &id))
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return scoped_ptr<VideoCaptureDevice>();
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  VideoCaptureDeviceAndroid* video_capture_device(
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new VideoCaptureDeviceAndroid(device_name));
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (video_capture_device->Init())
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return scoped_ptr<VideoCaptureDevice>(video_capture_device);
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DLOG(ERROR) << "Error creating Video Capture Device.";
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return scoped_ptr<VideoCaptureDevice>();
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid VideoCaptureDeviceFactoryAndroid::GetDeviceNames(
55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VideoCaptureDevice::Names* device_names) {
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  device_names->clear();
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  JNIEnv* env = AttachCurrentThread();
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  int num_cameras = Java_ChromiumCameraInfo_getNumberOfCameras(
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      env, base::android::GetApplicationContext());
63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DVLOG(1) << "VideoCaptureDevice::GetDeviceNames: num_cameras=" << num_cameras;
64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (num_cameras <= 0)
65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
66e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (int camera_id = num_cameras - 1; camera_id >= 0; --camera_id) {
68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ScopedJavaLocalRef<jobject> ci =
69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        Java_ChromiumCameraInfo_getAt(env, camera_id);
70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
71e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VideoCaptureDevice::Name name(
72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::android::ConvertJavaStringToUTF8(
73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            Java_ChromiumCameraInfo_getDeviceName(env, ci.obj())),
74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        base::StringPrintf("%d", Java_ChromiumCameraInfo_getId(env, ci.obj())));
75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    device_names->push_back(name);
76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    DVLOG(1) << "VideoCaptureDeviceFactoryAndroid::GetDeviceNames: camera"
78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             << "device_name=" << name.name() << ", unique_id=" << name.id()
79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             << ", orientation "
80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch             << Java_ChromiumCameraInfo_getOrientation(env, ci.obj());
81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid VideoCaptureDeviceFactoryAndroid::GetDeviceSupportedFormats(
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const VideoCaptureDevice::Name& device,
86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VideoCaptureFormats* capture_formats) {
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  int id;
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (!base::StringToInt(device.id(), &id))
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  JNIEnv* env = AttachCurrentThread();
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  base::android::ScopedJavaLocalRef<jobjectArray> collected_formats =
93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      Java_VideoCaptureFactory_getDeviceSupportedFormats(env, id);
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (collected_formats.is_null())
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    return;
96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  jsize num_formats = env->GetArrayLength(collected_formats.obj());
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for (int i = 0; i < num_formats; ++i) {
99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    base::android::ScopedJavaLocalRef<jobject> format(
100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        env, env->GetObjectArrayElement(collected_formats.obj(), i));
101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VideoPixelFormat pixel_format = media::PIXEL_FORMAT_UNKNOWN;
103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    switch (media::Java_VideoCaptureFactory_getCaptureFormatPixelFormat(
104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        env, format.obj())) {
105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      case ANDROID_IMAGEFORMAT_YV12:
106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        pixel_format = media::PIXEL_FORMAT_YV12;
107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        break;
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      case ANDROID_IMAGEFORMAT_NV21:
109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        pixel_format = media::PIXEL_FORMAT_NV21;
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        break;
111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      default:
112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        break;
113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    }
114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    VideoCaptureFormat capture_format(
115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        gfx::Size(media::Java_VideoCaptureFactory_getCaptureFormatWidth(env,
116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      format.obj()),
117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                  media::Java_VideoCaptureFactory_getCaptureFormatHeight(env,
118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      format.obj())),
119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        media::Java_VideoCaptureFactory_getCaptureFormatFramerate(env,
120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                                                  format.obj()),
121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        pixel_format);
122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    capture_formats->push_back(capture_format);
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DVLOG(1) << device.name() << " " << capture_format.ToString();
124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
127e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}  // namespace media
128