| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/capture/video/android/video_capture_device_android.h" | 5 #include "media/capture/video/android/video_capture_device_android.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/android/jni_android.h" | 10 #include "base/android/jni_android.h" |
| 11 #include "base/android/jni_array.h" | 11 #include "base/android/jni_array.h" |
| 12 #include "base/android/jni_string.h" | 12 #include "base/android/jni_string.h" |
| 13 #include "base/numerics/safe_conversions.h" | 13 #include "base/numerics/safe_conversions.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "jni/VideoCapture_jni.h" | 16 #include "jni/VideoCapture_jni.h" |
| 16 #include "media/capture/video/android/photo_capabilities.h" | 17 #include "media/capture/video/android/photo_capabilities.h" |
| 17 #include "media/capture/video/android/video_capture_device_factory_android.h" | 18 #include "media/capture/video/android/video_capture_device_factory_android.h" |
| 18 #include "third_party/libyuv/include/libyuv.h" | 19 #include "third_party/libyuv/include/libyuv.h" |
| 19 | 20 |
| 20 using base::android::AttachCurrentThread; | 21 using base::android::AttachCurrentThread; |
| 21 using base::android::CheckException; | 22 using base::android::CheckException; |
| 22 using base::android::GetClass; | 23 using base::android::GetClass; |
| 23 using base::android::JavaParamRef; | 24 using base::android::JavaParamRef; |
| 24 using base::android::MethodID; | 25 using base::android::MethodID; |
| 25 using base::android::JavaRef; | 26 using base::android::JavaRef; |
| 26 using base::android::ScopedJavaLocalRef; | 27 using base::android::ScopedJavaLocalRef; |
| 27 | 28 |
| 28 namespace media { | 29 namespace media { |
| 29 | 30 |
| 30 // static | 31 // static |
| 31 bool VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice(JNIEnv* env) { | 32 bool VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice(JNIEnv* env) { |
| 32 return RegisterNativesImpl(env); | 33 return RegisterNativesImpl(env); |
| 33 } | 34 } |
| 34 | 35 |
| 35 VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid( | 36 VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid( |
| 36 const VideoCaptureDeviceDescriptor& device_descriptor) | 37 const VideoCaptureDeviceDescriptor& device_descriptor) |
| 37 : state_(kIdle), | 38 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 39 state_(kIdle), |
| 38 got_first_frame_(false), | 40 got_first_frame_(false), |
| 39 device_descriptor_(device_descriptor) {} | 41 device_descriptor_(device_descriptor), |
| 42 weak_ptr_factory_(this) {} |
| 40 | 43 |
| 41 VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() { | 44 VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() { |
| 42 DCHECK(thread_checker_.CalledOnValidThread()); | 45 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 43 StopAndDeAllocate(); | 46 StopAndDeAllocate(); |
| 44 } | 47 } |
| 45 | 48 |
| 46 bool VideoCaptureDeviceAndroid::Init() { | 49 bool VideoCaptureDeviceAndroid::Init() { |
| 47 int id; | 50 int id; |
| 48 if (!base::StringToInt(device_descriptor_.device_id, &id)) | 51 if (!base::StringToInt(device_descriptor_.device_id, &id)) |
| 49 return false; | 52 return false; |
| 50 | 53 |
| 51 j_capture_.Reset(VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid( | 54 j_capture_.Reset(VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid( |
| 52 id, reinterpret_cast<intptr_t>(this))); | 55 id, reinterpret_cast<intptr_t>(this))); |
| 53 return true; | 56 return true; |
| 54 } | 57 } |
| 55 | 58 |
| 56 void VideoCaptureDeviceAndroid::AllocateAndStart( | 59 void VideoCaptureDeviceAndroid::AllocateAndStart( |
| 57 const VideoCaptureParams& params, | 60 const VideoCaptureParams& params, |
| 58 std::unique_ptr<Client> client) { | 61 std::unique_ptr<Client> client) { |
| 59 DCHECK(thread_checker_.CalledOnValidThread()); | 62 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 60 { | 63 { |
| 61 base::AutoLock lock(lock_); | 64 base::AutoLock lock(lock_); |
| 62 if (state_ != kIdle) | 65 if (state_ != kIdle) |
| 63 return; | 66 return; |
| 64 client_ = std::move(client); | 67 client_ = std::move(client); |
| 65 got_first_frame_ = false; | 68 got_first_frame_ = false; |
| 66 } | 69 } |
| 67 | 70 |
| 68 JNIEnv* env = AttachCurrentThread(); | 71 JNIEnv* env = AttachCurrentThread(); |
| 69 | 72 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 98 << capture_format_.frame_rate << "fps"; | 101 << capture_format_.frame_rate << "fps"; |
| 99 | 102 |
| 100 ret = Java_VideoCapture_startCapture(env, j_capture_.obj()); | 103 ret = Java_VideoCapture_startCapture(env, j_capture_.obj()); |
| 101 if (!ret) { | 104 if (!ret) { |
| 102 SetErrorState(FROM_HERE, "failed to start capture"); | 105 SetErrorState(FROM_HERE, "failed to start capture"); |
| 103 return; | 106 return; |
| 104 } | 107 } |
| 105 | 108 |
| 106 { | 109 { |
| 107 base::AutoLock lock(lock_); | 110 base::AutoLock lock(lock_); |
| 108 state_ = kCapturing; | 111 state_ = kConfigured; |
| 109 } | 112 } |
| 110 } | 113 } |
| 111 | 114 |
| 112 void VideoCaptureDeviceAndroid::StopAndDeAllocate() { | 115 void VideoCaptureDeviceAndroid::StopAndDeAllocate() { |
| 113 DCHECK(thread_checker_.CalledOnValidThread()); | 116 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 114 { | 117 { |
| 115 base::AutoLock lock(lock_); | 118 base::AutoLock lock(lock_); |
| 116 if (state_ != kCapturing && state_ != kError) | 119 if (state_ != kConfigured && state_ != kError) |
| 117 return; | 120 return; |
| 118 } | 121 } |
| 119 | 122 |
| 120 JNIEnv* env = AttachCurrentThread(); | 123 JNIEnv* env = AttachCurrentThread(); |
| 121 | 124 |
| 122 const jboolean ret = Java_VideoCapture_stopCapture(env, j_capture_.obj()); | 125 const jboolean ret = Java_VideoCapture_stopCapture(env, j_capture_.obj()); |
| 123 if (!ret) { | 126 if (!ret) { |
| 124 SetErrorState(FROM_HERE, "failed to stop capture"); | 127 SetErrorState(FROM_HERE, "failed to stop capture"); |
| 125 return; | 128 return; |
| 126 } | 129 } |
| 127 | 130 |
| 128 { | 131 { |
| 129 base::AutoLock lock(lock_); | 132 base::AutoLock lock(lock_); |
| 130 state_ = kIdle; | 133 state_ = kIdle; |
| 131 client_.reset(); | 134 client_.reset(); |
| 132 } | 135 } |
| 133 | 136 |
| 134 Java_VideoCapture_deallocate(env, j_capture_.obj()); | 137 Java_VideoCapture_deallocate(env, j_capture_.obj()); |
| 135 } | 138 } |
| 136 | 139 |
| 137 void VideoCaptureDeviceAndroid::TakePhoto(TakePhotoCallback callback) { | 140 void VideoCaptureDeviceAndroid::TakePhoto(TakePhotoCallback callback) { |
| 138 DCHECK(thread_checker_.CalledOnValidThread()); | 141 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 139 { | 142 { |
| 140 base::AutoLock lock(lock_); | 143 base::AutoLock lock(lock_); |
| 141 if (state_ != kCapturing) | 144 if (state_ != kConfigured) |
| 142 return; | 145 return; |
| 146 if (!got_first_frame_) { // We have to wait until we get the first frame. |
| 147 photo_requests_queue_.push_back( |
| 148 base::Bind(&VideoCaptureDeviceAndroid::DoTakePhoto, |
| 149 weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback))); |
| 150 return; |
| 151 } |
| 143 } | 152 } |
| 144 | 153 DoTakePhoto(std::move(callback)); |
| 145 JNIEnv* env = AttachCurrentThread(); | |
| 146 | |
| 147 // Make copy on the heap so we can pass the pointer through JNI. | |
| 148 std::unique_ptr<TakePhotoCallback> heap_callback( | |
| 149 new TakePhotoCallback(std::move(callback))); | |
| 150 const intptr_t callback_id = reinterpret_cast<intptr_t>(heap_callback.get()); | |
| 151 if (!Java_VideoCapture_takePhoto(env, j_capture_.obj(), callback_id, | |
| 152 next_photo_resolution_.width(), | |
| 153 next_photo_resolution_.height())) | |
| 154 return; | |
| 155 | |
| 156 { | |
| 157 base::AutoLock lock(photo_callbacks_lock_); | |
| 158 photo_callbacks_.push_back(std::move(heap_callback)); | |
| 159 } | |
| 160 } | 154 } |
| 161 | 155 |
| 162 void VideoCaptureDeviceAndroid::GetPhotoCapabilities( | 156 void VideoCaptureDeviceAndroid::GetPhotoCapabilities( |
| 163 GetPhotoCapabilitiesCallback callback) { | 157 GetPhotoCapabilitiesCallback callback) { |
| 164 DCHECK(thread_checker_.CalledOnValidThread()); | 158 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 165 JNIEnv* env = AttachCurrentThread(); | 159 { |
| 166 | 160 base::AutoLock lock(lock_); |
| 167 PhotoCapabilities caps( | 161 if (state_ != kConfigured) |
| 168 Java_VideoCapture_getPhotoCapabilities(env, j_capture_.obj())); | 162 return; |
| 169 | 163 if (!got_first_frame_) { // We have to wait until we get the first frame. |
| 170 // TODO(mcasas): Manual member copying sucks, consider adding typemapping from | 164 photo_requests_queue_.push_back( |
| 171 // PhotoCapabilities to mojom::PhotoCapabilitiesPtr, https://crbug.com/622002. | 165 base::Bind(&VideoCaptureDeviceAndroid::DoGetPhotoCapabilities, |
| 172 mojom::PhotoCapabilitiesPtr photo_capabilities = | 166 weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback))); |
| 173 mojom::PhotoCapabilities::New(); | 167 return; |
| 174 photo_capabilities->iso = mojom::Range::New(); | 168 } |
| 175 photo_capabilities->iso->current = caps.getCurrentIso(); | 169 } |
| 176 photo_capabilities->iso->max = caps.getMaxIso(); | 170 DoGetPhotoCapabilities(std::move(callback)); |
| 177 photo_capabilities->iso->min = caps.getMinIso(); | |
| 178 photo_capabilities->height = mojom::Range::New(); | |
| 179 photo_capabilities->height->current = caps.getCurrentHeight(); | |
| 180 photo_capabilities->height->max = caps.getMaxHeight(); | |
| 181 photo_capabilities->height->min = caps.getMinHeight(); | |
| 182 photo_capabilities->width = mojom::Range::New(); | |
| 183 photo_capabilities->width->current = caps.getCurrentWidth(); | |
| 184 photo_capabilities->width->max = caps.getMaxWidth(); | |
| 185 photo_capabilities->width->min = caps.getMinWidth(); | |
| 186 photo_capabilities->zoom = mojom::Range::New(); | |
| 187 photo_capabilities->zoom->current = caps.getCurrentZoom(); | |
| 188 photo_capabilities->zoom->max = caps.getMaxZoom(); | |
| 189 photo_capabilities->zoom->min = caps.getMinZoom(); | |
| 190 photo_capabilities->focus_mode = caps.getAutoFocusInUse() | |
| 191 ? mojom::FocusMode::AUTO | |
| 192 : mojom::FocusMode::MANUAL; | |
| 193 callback.Run(std::move(photo_capabilities)); | |
| 194 } | 171 } |
| 195 | 172 |
| 196 void VideoCaptureDeviceAndroid::SetPhotoOptions( | 173 void VideoCaptureDeviceAndroid::SetPhotoOptions( |
| 197 mojom::PhotoSettingsPtr settings, | 174 mojom::PhotoSettingsPtr settings, |
| 198 SetPhotoOptionsCallback callback) { | 175 SetPhotoOptionsCallback callback) { |
| 199 DCHECK(thread_checker_.CalledOnValidThread()); | 176 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 200 JNIEnv* env = AttachCurrentThread(); | 177 { |
| 201 // |width| and/or |height| are kept for the next TakePhoto()s. | 178 base::AutoLock lock(lock_); |
| 202 if (settings->has_width || settings->has_height) | 179 if (state_ != kConfigured) |
| 203 next_photo_resolution_.SetSize(0, 0); | 180 return; |
| 204 if (settings->has_width) { | 181 if (!got_first_frame_) { // We have to wait until we get the first frame. |
| 205 next_photo_resolution_.set_width( | 182 photo_requests_queue_.push_back( |
| 206 base::saturated_cast<int>(settings->width)); | 183 base::Bind(&VideoCaptureDeviceAndroid::DoSetPhotoOptions, |
| 184 weak_ptr_factory_.GetWeakPtr(), base::Passed(&settings), |
| 185 base::Passed(&callback))); |
| 186 return; |
| 187 } |
| 207 } | 188 } |
| 208 if (settings->has_height) { | 189 DoSetPhotoOptions(std::move(settings), std::move(callback)); |
| 209 next_photo_resolution_.set_height( | |
| 210 base::saturated_cast<int>(settings->height)); | |
| 211 } | |
| 212 | |
| 213 if (settings->has_zoom) | |
| 214 Java_VideoCapture_setZoom(env, j_capture_.obj(), settings->zoom); | |
| 215 callback.Run(true); | |
| 216 } | 190 } |
| 217 | 191 |
| 218 void VideoCaptureDeviceAndroid::OnFrameAvailable( | 192 void VideoCaptureDeviceAndroid::OnFrameAvailable( |
| 219 JNIEnv* env, | 193 JNIEnv* env, |
| 220 const JavaParamRef<jobject>& obj, | 194 const JavaParamRef<jobject>& obj, |
| 221 const JavaParamRef<jbyteArray>& data, | 195 const JavaParamRef<jbyteArray>& data, |
| 222 jint length, | 196 jint length, |
| 223 jint rotation) { | 197 jint rotation) { |
| 224 { | 198 { |
| 225 base::AutoLock lock(lock_); | 199 base::AutoLock lock(lock_); |
| 226 if (state_ != kCapturing || !client_) | 200 if (state_ != kConfigured || !client_) |
| 227 return; | 201 return; |
| 228 } | 202 } |
| 229 | 203 |
| 230 jbyte* buffer = env->GetByteArrayElements(data, NULL); | 204 jbyte* buffer = env->GetByteArrayElements(data, NULL); |
| 231 if (!buffer) { | 205 if (!buffer) { |
| 232 LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: " | 206 LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: " |
| 233 "failed to GetByteArrayElements"; | 207 "failed to GetByteArrayElements"; |
| 234 return; | 208 return; |
| 235 } | 209 } |
| 236 | 210 |
| 237 const base::TimeTicks current_time = base::TimeTicks::Now(); | 211 const base::TimeTicks current_time = base::TimeTicks::Now(); |
| 238 if (!got_first_frame_) { | 212 { |
| 239 // Set aside one frame allowance for fluctuation. | 213 base::AutoLock lock(lock_); |
| 240 expected_next_frame_time_ = current_time - frame_interval_; | 214 if (!got_first_frame_) { |
| 241 first_ref_time_ = current_time; | 215 // Set aside one frame allowance for fluctuation. |
| 242 got_first_frame_ = true; | 216 expected_next_frame_time_ = current_time - frame_interval_; |
| 217 first_ref_time_ = current_time; |
| 218 got_first_frame_ = true; |
| 219 |
| 220 for (const auto& request : photo_requests_queue_) |
| 221 main_task_runner_->PostTask(FROM_HERE, request); |
| 222 photo_requests_queue_.clear(); |
| 223 } |
| 243 } | 224 } |
| 244 | 225 |
| 245 // Deliver the frame when it doesn't arrive too early. | 226 // Deliver the frame when it doesn't arrive too early. |
| 246 if (expected_next_frame_time_ <= current_time) { | 227 if (expected_next_frame_time_ <= current_time) { |
| 247 expected_next_frame_time_ += frame_interval_; | 228 expected_next_frame_time_ += frame_interval_; |
| 248 | 229 |
| 249 // TODO(qiangchen): Investigate how to get raw timestamp for Android, | 230 // TODO(qiangchen): Investigate how to get raw timestamp for Android, |
| 250 // rather than using reference time to calculate timestamp. | 231 // rather than using reference time to calculate timestamp. |
| 251 base::AutoLock lock(lock_); | 232 base::AutoLock lock(lock_); |
| 252 if (!client_) | 233 if (!client_) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 265 jint y_stride, | 246 jint y_stride, |
| 266 jobject u_buffer, | 247 jobject u_buffer, |
| 267 jobject v_buffer, | 248 jobject v_buffer, |
| 268 jint uv_row_stride, | 249 jint uv_row_stride, |
| 269 jint uv_pixel_stride, | 250 jint uv_pixel_stride, |
| 270 jint width, | 251 jint width, |
| 271 jint height, | 252 jint height, |
| 272 jint rotation) { | 253 jint rotation) { |
| 273 { | 254 { |
| 274 base::AutoLock lock(lock_); | 255 base::AutoLock lock(lock_); |
| 275 if (state_ != kCapturing || !client_) | 256 if (state_ != kConfigured || !client_) |
| 276 return; | 257 return; |
| 277 } | 258 } |
| 278 | 259 |
| 279 const base::TimeTicks current_time = base::TimeTicks::Now(); | 260 const base::TimeTicks current_time = base::TimeTicks::Now(); |
| 280 if (!got_first_frame_) { | 261 { |
| 281 // Set aside one frame allowance for fluctuation. | 262 base::AutoLock lock(lock_); |
| 282 expected_next_frame_time_ = current_time - frame_interval_; | 263 if (!got_first_frame_) { |
| 283 first_ref_time_ = current_time; | 264 // Set aside one frame allowance for fluctuation. |
| 284 got_first_frame_ = true; | 265 expected_next_frame_time_ = current_time - frame_interval_; |
| 266 first_ref_time_ = current_time; |
| 267 got_first_frame_ = true; |
| 268 |
| 269 for (const auto& request : photo_requests_queue_) |
| 270 main_task_runner_->PostTask(FROM_HERE, request); |
| 271 photo_requests_queue_.clear(); |
| 272 } |
| 285 } | 273 } |
| 286 | 274 |
| 287 uint8_t* const y_src = | 275 uint8_t* const y_src = |
| 288 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer)); | 276 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer)); |
| 289 CHECK(y_src); | 277 CHECK(y_src); |
| 290 uint8_t* const u_src = | 278 uint8_t* const u_src = |
| 291 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer)); | 279 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer)); |
| 292 CHECK(u_src); | 280 CHECK(u_src); |
| 293 uint8_t* const v_src = | 281 uint8_t* const v_src = |
| 294 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer)); | 282 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer)); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 const std::string& reason) { | 367 const std::string& reason) { |
| 380 { | 368 { |
| 381 base::AutoLock lock(lock_); | 369 base::AutoLock lock(lock_); |
| 382 state_ = kError; | 370 state_ = kError; |
| 383 if (!client_) | 371 if (!client_) |
| 384 return; | 372 return; |
| 385 client_->OnError(from_here, reason); | 373 client_->OnError(from_here, reason); |
| 386 } | 374 } |
| 387 } | 375 } |
| 388 | 376 |
| 377 void VideoCaptureDeviceAndroid::DoTakePhoto(TakePhotoCallback callback) { |
| 378 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 379 #if DCHECK_IS_ON() |
| 380 { |
| 381 base::AutoLock lock(lock_); |
| 382 DCHECK_EQ(kConfigured, state_); |
| 383 DCHECK(got_first_frame_); |
| 384 } |
| 385 #endif |
| 386 JNIEnv* env = AttachCurrentThread(); |
| 387 |
| 388 // Make copy on the heap so we can pass the pointer through JNI. |
| 389 std::unique_ptr<TakePhotoCallback> heap_callback( |
| 390 new TakePhotoCallback(std::move(callback))); |
| 391 const intptr_t callback_id = reinterpret_cast<intptr_t>(heap_callback.get()); |
| 392 if (!Java_VideoCapture_takePhoto(env, j_capture_.obj(), callback_id, |
| 393 next_photo_resolution_.width(), |
| 394 next_photo_resolution_.height())) |
| 395 return; |
| 396 |
| 397 { |
| 398 base::AutoLock lock(photo_callbacks_lock_); |
| 399 photo_callbacks_.push_back(std::move(heap_callback)); |
| 400 } |
| 401 } |
| 402 |
| 403 void VideoCaptureDeviceAndroid::DoGetPhotoCapabilities( |
| 404 GetPhotoCapabilitiesCallback callback) { |
| 405 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 406 #if DCHECK_IS_ON() |
| 407 { |
| 408 base::AutoLock lock(lock_); |
| 409 DCHECK_EQ(kConfigured, state_); |
| 410 DCHECK(got_first_frame_); |
| 411 } |
| 412 #endif |
| 413 JNIEnv* env = AttachCurrentThread(); |
| 414 |
| 415 PhotoCapabilities caps( |
| 416 Java_VideoCapture_getPhotoCapabilities(env, j_capture_.obj())); |
| 417 |
| 418 // TODO(mcasas): Manual member copying sucks, consider adding typemapping from |
| 419 // PhotoCapabilities to mojom::PhotoCapabilitiesPtr, https://crbug.com/622002. |
| 420 mojom::PhotoCapabilitiesPtr photo_capabilities = |
| 421 mojom::PhotoCapabilities::New(); |
| 422 photo_capabilities->iso = mojom::Range::New(); |
| 423 photo_capabilities->iso->current = caps.getCurrentIso(); |
| 424 photo_capabilities->iso->max = caps.getMaxIso(); |
| 425 photo_capabilities->iso->min = caps.getMinIso(); |
| 426 photo_capabilities->height = mojom::Range::New(); |
| 427 photo_capabilities->height->current = caps.getCurrentHeight(); |
| 428 photo_capabilities->height->max = caps.getMaxHeight(); |
| 429 photo_capabilities->height->min = caps.getMinHeight(); |
| 430 photo_capabilities->width = mojom::Range::New(); |
| 431 photo_capabilities->width->current = caps.getCurrentWidth(); |
| 432 photo_capabilities->width->max = caps.getMaxWidth(); |
| 433 photo_capabilities->width->min = caps.getMinWidth(); |
| 434 photo_capabilities->zoom = mojom::Range::New(); |
| 435 photo_capabilities->zoom->current = caps.getCurrentZoom(); |
| 436 photo_capabilities->zoom->max = caps.getMaxZoom(); |
| 437 photo_capabilities->zoom->min = caps.getMinZoom(); |
| 438 photo_capabilities->focus_mode = caps.getAutoFocusInUse() |
| 439 ? mojom::FocusMode::AUTO |
| 440 : mojom::FocusMode::MANUAL; |
| 441 callback.Run(std::move(photo_capabilities)); |
| 442 } |
| 443 |
| 444 void VideoCaptureDeviceAndroid::DoSetPhotoOptions( |
| 445 mojom::PhotoSettingsPtr settings, |
| 446 SetPhotoOptionsCallback callback) { |
| 447 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
| 448 #if DCHECK_IS_ON() |
| 449 { |
| 450 base::AutoLock lock(lock_); |
| 451 DCHECK_EQ(kConfigured, state_); |
| 452 DCHECK(got_first_frame_); |
| 453 } |
| 454 #endif |
| 455 JNIEnv* env = AttachCurrentThread(); |
| 456 |
| 457 // |width| and/or |height| are kept for the next TakePhoto()s. |
| 458 if (settings->has_width || settings->has_height) |
| 459 next_photo_resolution_.SetSize(0, 0); |
| 460 if (settings->has_width) { |
| 461 next_photo_resolution_.set_width( |
| 462 base::saturated_cast<int>(settings->width)); |
| 463 } |
| 464 if (settings->has_height) { |
| 465 next_photo_resolution_.set_height( |
| 466 base::saturated_cast<int>(settings->height)); |
| 467 } |
| 468 |
| 469 if (settings->has_zoom) |
| 470 Java_VideoCapture_setZoom(env, j_capture_.obj(), settings->zoom); |
| 471 |
| 472 callback.Run(true); |
| 473 } |
| 474 |
| 389 } // namespace media | 475 } // namespace media |
| OLD | NEW |