Updating XTBs based on .GRDs from branch master
[chromium-blink-merge.git] / media / capture / video / android / video_capture_device_android.cc
blob9df39c4645fae0105bc3fe2d915ed1a22c6ad130
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/capture/video/android/video_capture_device_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "jni/VideoCapture_jni.h"
11 #include "media/capture/video/android/video_capture_device_factory_android.h"
13 using base::android::AttachCurrentThread;
14 using base::android::CheckException;
15 using base::android::GetClass;
16 using base::android::MethodID;
17 using base::android::JavaRef;
18 using base::android::ScopedJavaLocalRef;
20 namespace media {
22 // static
23 bool VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice(JNIEnv* env) {
24 return RegisterNativesImpl(env);
27 const std::string VideoCaptureDevice::Name::GetModel() const {
28 // Android cameras are not typically USB devices, and this method is currently
29 // only used for USB model identifiers, so this implementation just indicates
30 // an unknown device model.
31 return "";
34 VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid(const Name& device_name)
35 : state_(kIdle), got_first_frame_(false), device_name_(device_name) {
38 VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() {
39 StopAndDeAllocate();
42 bool VideoCaptureDeviceAndroid::Init() {
43 int id;
44 if (!base::StringToInt(device_name_.id(), &id))
45 return false;
47 j_capture_.Reset(VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid(
48 id, reinterpret_cast<intptr_t>(this)));
49 return true;
52 void VideoCaptureDeviceAndroid::AllocateAndStart(
53 const VideoCaptureParams& params,
54 scoped_ptr<Client> client) {
55 DVLOG(1) << "VideoCaptureDeviceAndroid::AllocateAndStart";
57 base::AutoLock lock(lock_);
58 if (state_ != kIdle)
59 return;
60 client_ = client.Pass();
61 got_first_frame_ = false;
64 JNIEnv* env = AttachCurrentThread();
66 jboolean ret = Java_VideoCapture_allocate(
67 env, j_capture_.obj(), params.requested_format.frame_size.width(),
68 params.requested_format.frame_size.height(),
69 params.requested_format.frame_rate);
70 if (!ret) {
71 SetErrorState("failed to allocate");
72 return;
75 // Store current width and height.
76 capture_format_.frame_size.SetSize(
77 Java_VideoCapture_queryWidth(env, j_capture_.obj()),
78 Java_VideoCapture_queryHeight(env, j_capture_.obj()));
79 capture_format_.frame_rate =
80 Java_VideoCapture_queryFrameRate(env, j_capture_.obj());
81 capture_format_.pixel_format = GetColorspace();
82 DCHECK_NE(capture_format_.pixel_format,
83 media::VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN);
84 CHECK(capture_format_.frame_size.GetArea() > 0);
85 CHECK(!(capture_format_.frame_size.width() % 2));
86 CHECK(!(capture_format_.frame_size.height() % 2));
88 if (capture_format_.frame_rate > 0) {
89 frame_interval_ = base::TimeDelta::FromMicroseconds(
90 (base::Time::kMicrosecondsPerSecond + capture_format_.frame_rate - 1) /
91 capture_format_.frame_rate);
94 DVLOG(1) << "VideoCaptureDeviceAndroid::Allocate: queried frame_size="
95 << capture_format_.frame_size.ToString()
96 << ", frame_rate=" << capture_format_.frame_rate;
98 ret = Java_VideoCapture_startCapture(env, j_capture_.obj());
99 if (!ret) {
100 SetErrorState("failed to start capture");
101 return;
105 base::AutoLock lock(lock_);
106 state_ = kCapturing;
110 void VideoCaptureDeviceAndroid::StopAndDeAllocate() {
111 DVLOG(1) << "VideoCaptureDeviceAndroid::StopAndDeAllocate";
113 base::AutoLock lock(lock_);
114 if (state_ != kCapturing && state_ != kError)
115 return;
118 JNIEnv* env = AttachCurrentThread();
120 jboolean ret = Java_VideoCapture_stopCapture(env, j_capture_.obj());
121 if (!ret) {
122 SetErrorState("failed to stop capture");
123 return;
127 base::AutoLock lock(lock_);
128 state_ = kIdle;
129 client_.reset();
132 Java_VideoCapture_deallocate(env, j_capture_.obj());
135 void VideoCaptureDeviceAndroid::OnFrameAvailable(JNIEnv* env,
136 jobject obj,
137 jbyteArray data,
138 jint length,
139 jint rotation) {
140 DVLOG(3) << "VideoCaptureDeviceAndroid::OnFrameAvailable: length =" << length;
142 base::AutoLock lock(lock_);
143 if (state_ != kCapturing || !client_.get())
144 return;
146 jbyte* buffer = env->GetByteArrayElements(data, NULL);
147 if (!buffer) {
148 LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: "
149 "failed to GetByteArrayElements";
150 return;
153 base::TimeTicks current_time = base::TimeTicks::Now();
154 if (!got_first_frame_) {
155 // Set aside one frame allowance for fluctuation.
156 expected_next_frame_time_ = current_time - frame_interval_;
157 got_first_frame_ = true;
160 // Deliver the frame when it doesn't arrive too early.
161 if (expected_next_frame_time_ <= current_time) {
162 expected_next_frame_time_ += frame_interval_;
164 client_->OnIncomingCapturedData(reinterpret_cast<uint8*>(buffer), length,
165 capture_format_, rotation,
166 base::TimeTicks::Now());
169 env->ReleaseByteArrayElements(data, buffer, JNI_ABORT);
172 void VideoCaptureDeviceAndroid::OnError(JNIEnv* env,
173 jobject obj,
174 jstring message) {
175 SetErrorState(base::android::ConvertJavaStringToUTF8(env, message));
178 VideoCapturePixelFormat VideoCaptureDeviceAndroid::GetColorspace() {
179 JNIEnv* env = AttachCurrentThread();
180 int current_capture_colorspace =
181 Java_VideoCapture_getColorspace(env, j_capture_.obj());
182 switch (current_capture_colorspace) {
183 case ANDROID_IMAGE_FORMAT_YV12:
184 return media::VIDEO_CAPTURE_PIXEL_FORMAT_YV12;
185 case ANDROID_IMAGE_FORMAT_YUV_420_888:
186 return media::VIDEO_CAPTURE_PIXEL_FORMAT_I420;
187 case ANDROID_IMAGE_FORMAT_NV21:
188 return media::VIDEO_CAPTURE_PIXEL_FORMAT_NV21;
189 case ANDROID_IMAGE_FORMAT_UNKNOWN:
190 default:
191 return media::VIDEO_CAPTURE_PIXEL_FORMAT_UNKNOWN;
195 void VideoCaptureDeviceAndroid::SetErrorState(const std::string& reason) {
197 base::AutoLock lock(lock_);
198 state_ = kError;
200 client_->OnError(reason);
203 } // namespace media