Chromium Code Reviews| 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" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 // only used for USB model identifiers, so this implementation just indicates | 36 // only used for USB model identifiers, so this implementation just indicates |
| 37 // an unknown device model. | 37 // an unknown device model. |
| 38 return ""; | 38 return ""; |
| 39 } | 39 } |
| 40 | 40 |
| 41 VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid(const Name& device_name) | 41 VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid(const Name& device_name) |
| 42 : state_(kIdle), got_first_frame_(false), device_name_(device_name) { | 42 : state_(kIdle), got_first_frame_(false), device_name_(device_name) { |
| 43 } | 43 } |
| 44 | 44 |
| 45 VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() { | 45 VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() { |
| 46 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 46 StopAndDeAllocate(); | 47 StopAndDeAllocate(); |
| 47 } | 48 } |
| 48 | 49 |
| 49 bool VideoCaptureDeviceAndroid::Init() { | 50 bool VideoCaptureDeviceAndroid::Init() { |
| 50 int id; | 51 int id; |
| 51 if (!base::StringToInt(device_name_.id(), &id)) | 52 if (!base::StringToInt(device_name_.id(), &id)) |
| 52 return false; | 53 return false; |
| 53 | 54 |
| 54 j_capture_.Reset(VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid( | 55 j_capture_.Reset(VideoCaptureDeviceFactoryAndroid::createVideoCaptureAndroid( |
| 55 id, reinterpret_cast<intptr_t>(this))); | 56 id, reinterpret_cast<intptr_t>(this))); |
| 56 return true; | 57 return true; |
| 57 } | 58 } |
| 58 | 59 |
| 59 void VideoCaptureDeviceAndroid::AllocateAndStart( | 60 void VideoCaptureDeviceAndroid::AllocateAndStart( |
| 60 const VideoCaptureParams& params, | 61 const VideoCaptureParams& params, |
| 61 std::unique_ptr<Client> client) { | 62 std::unique_ptr<Client> client) { |
| 62 DVLOG(1) << __FUNCTION__; | 63 DCHECK(thread_checker_.CalledOnValidThread()); |
| 63 { | 64 { |
| 64 base::AutoLock lock(lock_); | 65 base::AutoLock lock(lock_); |
| 65 if (state_ != kIdle) | 66 if (state_ != kIdle) |
| 66 return; | 67 return; |
| 67 client_ = std::move(client); | 68 client_ = std::move(client); |
| 68 got_first_frame_ = false; | 69 got_first_frame_ = false; |
| 69 } | 70 } |
| 70 | 71 |
| 71 JNIEnv* env = AttachCurrentThread(); | 72 JNIEnv* env = AttachCurrentThread(); |
| 72 | 73 |
| 73 jboolean ret = Java_VideoCapture_allocate( | 74 jboolean ret = Java_VideoCapture_allocate( |
| 74 env, j_capture_.obj(), params.requested_format.frame_size.width(), | 75 env, j_capture_.obj(), params.requested_format.frame_size.width(), |
| 75 params.requested_format.frame_size.height(), | 76 params.requested_format.frame_size.height(), |
| 76 params.requested_format.frame_rate); | 77 params.requested_format.frame_rate); |
| 77 if (!ret) { | 78 if (!ret) { |
| 78 SetErrorState(FROM_HERE, "failed to allocate"); | 79 SetErrorState(FROM_HERE, "failed to allocate"); |
| 79 return; | 80 return; |
| 80 } | 81 } |
| 81 | 82 |
| 82 // Store current width and height. | |
| 83 capture_format_.frame_size.SetSize( | 83 capture_format_.frame_size.SetSize( |
| 84 Java_VideoCapture_queryWidth(env, j_capture_.obj()), | 84 Java_VideoCapture_queryWidth(env, j_capture_.obj()), |
| 85 Java_VideoCapture_queryHeight(env, j_capture_.obj())); | 85 Java_VideoCapture_queryHeight(env, j_capture_.obj())); |
| 86 capture_format_.frame_rate = | 86 capture_format_.frame_rate = |
| 87 Java_VideoCapture_queryFrameRate(env, j_capture_.obj()); | 87 Java_VideoCapture_queryFrameRate(env, j_capture_.obj()); |
| 88 capture_format_.pixel_format = GetColorspace(); | 88 capture_format_.pixel_format = GetColorspace(); |
| 89 DCHECK_NE(capture_format_.pixel_format, media::PIXEL_FORMAT_UNKNOWN); | 89 DCHECK_NE(capture_format_.pixel_format, media::PIXEL_FORMAT_UNKNOWN); |
| 90 CHECK(capture_format_.frame_size.GetArea() > 0); | 90 CHECK(capture_format_.frame_size.GetArea() > 0); |
| 91 CHECK(!(capture_format_.frame_size.width() % 2)); | 91 CHECK(!(capture_format_.frame_size.width() % 2)); |
| 92 CHECK(!(capture_format_.frame_size.height() % 2)); | 92 CHECK(!(capture_format_.frame_size.height() % 2)); |
| 93 | 93 |
| 94 if (capture_format_.frame_rate > 0) { | 94 if (capture_format_.frame_rate > 0) { |
| 95 frame_interval_ = base::TimeDelta::FromMicroseconds( | 95 frame_interval_ = base::TimeDelta::FromMicroseconds( |
| 96 (base::Time::kMicrosecondsPerSecond + capture_format_.frame_rate - 1) / | 96 (base::Time::kMicrosecondsPerSecond + capture_format_.frame_rate - 1) / |
| 97 capture_format_.frame_rate); | 97 capture_format_.frame_rate); |
| 98 } | 98 } |
| 99 | 99 |
| 100 DVLOG(1) << "VideoCaptureDeviceAndroid::Allocate: queried frame_size=" | 100 DVLOG(1) << __FUNCTION__ << " requested (" |
| 101 << capture_format_.frame_size.ToString() | 101 << capture_format_.frame_size.ToString() << ")@ " |
| 102 << ", frame_rate=" << capture_format_.frame_rate; | 102 << capture_format_.frame_rate << "fps"; |
| 103 | 103 |
| 104 ret = Java_VideoCapture_startCapture(env, j_capture_.obj()); | 104 ret = Java_VideoCapture_startCapture(env, j_capture_.obj()); |
| 105 if (!ret) { | 105 if (!ret) { |
| 106 SetErrorState(FROM_HERE, "failed to start capture"); | 106 SetErrorState(FROM_HERE, "failed to start capture"); |
| 107 return; | 107 return; |
| 108 } | 108 } |
| 109 | 109 |
| 110 { | 110 { |
| 111 base::AutoLock lock(lock_); | 111 base::AutoLock lock(lock_); |
| 112 state_ = kCapturing; | 112 state_ = kCapturing; |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 | 115 |
| 116 void VideoCaptureDeviceAndroid::StopAndDeAllocate() { | 116 void VideoCaptureDeviceAndroid::StopAndDeAllocate() { |
| 117 DVLOG(1) << __FUNCTION__; | 117 DCHECK(thread_checker_.CalledOnValidThread()); |
| 118 { | 118 { |
| 119 base::AutoLock lock(lock_); | 119 base::AutoLock lock(lock_); |
| 120 if (state_ != kCapturing && state_ != kError) | 120 if (state_ != kCapturing && state_ != kError) |
| 121 return; | 121 return; |
| 122 } | 122 } |
| 123 | 123 |
| 124 JNIEnv* env = AttachCurrentThread(); | 124 JNIEnv* env = AttachCurrentThread(); |
| 125 | 125 |
| 126 jboolean ret = Java_VideoCapture_stopCapture(env, j_capture_.obj()); | 126 const jboolean ret = Java_VideoCapture_stopCapture(env, j_capture_.obj()); |
| 127 if (!ret) { | 127 if (!ret) { |
| 128 SetErrorState(FROM_HERE, "failed to stop capture"); | 128 SetErrorState(FROM_HERE, "failed to stop capture"); |
| 129 return; | 129 return; |
| 130 } | 130 } |
| 131 | 131 |
| 132 { | 132 { |
| 133 base::AutoLock lock(lock_); | 133 base::AutoLock lock(lock_); |
| 134 state_ = kIdle; | 134 state_ = kIdle; |
| 135 client_.reset(); | 135 client_.reset(); |
| 136 } | 136 } |
| 137 | 137 |
| 138 Java_VideoCapture_deallocate(env, j_capture_.obj()); | 138 Java_VideoCapture_deallocate(env, j_capture_.obj()); |
| 139 } | 139 } |
| 140 | 140 |
| 141 void VideoCaptureDeviceAndroid::TakePhoto(TakePhotoCallback callback) { | 141 void VideoCaptureDeviceAndroid::TakePhoto(TakePhotoCallback callback) { |
| 142 DVLOG(1) << __FUNCTION__; | 142 DCHECK(thread_checker_.CalledOnValidThread()); |
| 143 { | 143 { |
| 144 base::AutoLock lock(lock_); | 144 base::AutoLock lock(lock_); |
| 145 if (state_ != kCapturing) | 145 if (state_ != kCapturing) |
| 146 return; | 146 return; |
| 147 } | 147 } |
| 148 | 148 |
| 149 JNIEnv* env = AttachCurrentThread(); | 149 JNIEnv* env = AttachCurrentThread(); |
| 150 | 150 |
| 151 // Make copy on the heap so we can pass the pointer through JNI. | 151 // Make copy on the heap so we can pass the pointer through JNI. |
| 152 std::unique_ptr<TakePhotoCallback> heap_callback( | 152 std::unique_ptr<TakePhotoCallback> heap_callback( |
| 153 new TakePhotoCallback(std::move(callback))); | 153 new TakePhotoCallback(std::move(callback))); |
| 154 const intptr_t callback_id = reinterpret_cast<intptr_t>(heap_callback.get()); | 154 const intptr_t callback_id = reinterpret_cast<intptr_t>(heap_callback.get()); |
| 155 if (!Java_VideoCapture_takePhoto(env, j_capture_.obj(), callback_id, | 155 if (!Java_VideoCapture_takePhoto(env, j_capture_.obj(), callback_id, |
| 156 next_photo_resolution_.width(), | 156 next_photo_resolution_.width(), |
| 157 next_photo_resolution_.height())) | 157 next_photo_resolution_.height())) |
| 158 return; | 158 return; |
| 159 | 159 |
| 160 { | 160 { |
| 161 base::AutoLock lock(photo_callbacks_lock_); | 161 base::AutoLock lock(photo_callbacks_lock_); |
| 162 photo_callbacks_.push_back(std::move(heap_callback)); | 162 photo_callbacks_.push_back(std::move(heap_callback)); |
| 163 } | 163 } |
| 164 } | 164 } |
| 165 | 165 |
| 166 void VideoCaptureDeviceAndroid::GetPhotoCapabilities( | 166 void VideoCaptureDeviceAndroid::GetPhotoCapabilities( |
| 167 GetPhotoCapabilitiesCallback callback) { | 167 GetPhotoCapabilitiesCallback callback) { |
| 168 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 168 JNIEnv* env = AttachCurrentThread(); | 169 JNIEnv* env = AttachCurrentThread(); |
| 169 | 170 |
| 170 PhotoCapabilities caps( | 171 PhotoCapabilities caps( |
| 171 Java_VideoCapture_getPhotoCapabilities(env, j_capture_.obj())); | 172 Java_VideoCapture_getPhotoCapabilities(env, j_capture_.obj())); |
| 172 | 173 |
| 173 // TODO(mcasas): Manual member copying sucks, consider adding typemapping from | 174 // TODO(mcasas): Manual member copying sucks, consider adding typemapping from |
| 174 // PhotoCapabilities to mojom::PhotoCapabilitiesPtr, https://crbug.com/622002. | 175 // PhotoCapabilities to mojom::PhotoCapabilitiesPtr, https://crbug.com/622002. |
| 175 mojom::PhotoCapabilitiesPtr photo_capabilities = | 176 mojom::PhotoCapabilitiesPtr photo_capabilities = |
| 176 mojom::PhotoCapabilities::New(); | 177 mojom::PhotoCapabilities::New(); |
| 177 photo_capabilities->iso = mojom::Range::New(); | 178 photo_capabilities->iso = mojom::Range::New(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 192 photo_capabilities->zoom->min = caps.getMinZoom(); | 193 photo_capabilities->zoom->min = caps.getMinZoom(); |
| 193 photo_capabilities->focus_mode = caps.getAutoFocusInUse() | 194 photo_capabilities->focus_mode = caps.getAutoFocusInUse() |
| 194 ? mojom::FocusMode::AUTO | 195 ? mojom::FocusMode::AUTO |
| 195 : mojom::FocusMode::MANUAL; | 196 : mojom::FocusMode::MANUAL; |
| 196 callback.Run(std::move(photo_capabilities)); | 197 callback.Run(std::move(photo_capabilities)); |
| 197 } | 198 } |
| 198 | 199 |
| 199 void VideoCaptureDeviceAndroid::SetPhotoOptions( | 200 void VideoCaptureDeviceAndroid::SetPhotoOptions( |
| 200 mojom::PhotoSettingsPtr settings, | 201 mojom::PhotoSettingsPtr settings, |
| 201 SetPhotoOptionsCallback callback) { | 202 SetPhotoOptionsCallback callback) { |
| 203 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 202 JNIEnv* env = AttachCurrentThread(); | 204 JNIEnv* env = AttachCurrentThread(); |
| 203 // |width| and/or |height| are kept for the next TakePhoto()s. | 205 // |width| and/or |height| are kept for the next TakePhoto()s. |
| 204 if (settings->has_width || settings->has_height) | 206 if (settings->has_width || settings->has_height) |
| 205 next_photo_resolution_.SetSize(0, 0); | 207 next_photo_resolution_.SetSize(0, 0); |
| 206 if (settings->has_width) { | 208 if (settings->has_width) { |
| 207 next_photo_resolution_.set_width( | 209 next_photo_resolution_.set_width( |
| 208 base::saturated_cast<int>(settings->width)); | 210 base::saturated_cast<int>(settings->width)); |
| 209 } | 211 } |
| 210 if (settings->has_height) { | 212 if (settings->has_height) { |
| 211 next_photo_resolution_.set_height( | 213 next_photo_resolution_.set_height( |
| 212 base::saturated_cast<int>(settings->height)); | 214 base::saturated_cast<int>(settings->height)); |
| 213 } | 215 } |
| 214 | 216 |
| 215 if (settings->has_zoom) | 217 if (settings->has_zoom) |
| 216 Java_VideoCapture_setZoom(env, j_capture_.obj(), settings->zoom); | 218 Java_VideoCapture_setZoom(env, j_capture_.obj(), settings->zoom); |
| 217 callback.Run(true); | 219 callback.Run(true); |
| 218 } | 220 } |
| 219 | 221 |
| 220 void VideoCaptureDeviceAndroid::OnFrameAvailable( | 222 void VideoCaptureDeviceAndroid::OnFrameAvailable( |
| 221 JNIEnv* env, | 223 JNIEnv* env, |
| 222 const JavaParamRef<jobject>& obj, | 224 const JavaParamRef<jobject>& obj, |
| 223 const JavaParamRef<jbyteArray>& data, | 225 const JavaParamRef<jbyteArray>& data, |
| 224 jint length, | 226 jint length, |
| 225 jint rotation) { | 227 jint rotation) { |
| 226 DVLOG(3) << __FUNCTION__ << " length =" << length; | 228 DVLOG(3) << __FUNCTION__ << " length =" << length; |
| 227 | 229 |
| 228 base::AutoLock lock(lock_); | 230 { |
| 229 if (state_ != kCapturing || !client_.get()) | 231 base::AutoLock lock(lock_); |
| 230 return; | 232 if (state_ != kCapturing || !client_.get()) |
| 233 return; | |
| 234 } | |
|
chfremer
2016/07/27 17:07:59
Not sure we really can reduce the scope of the loc
mcasas
2016/07/27 18:40:54
You're right, done.
| |
| 231 | 235 |
| 232 jbyte* buffer = env->GetByteArrayElements(data, NULL); | 236 jbyte* buffer = env->GetByteArrayElements(data, NULL); |
| 233 if (!buffer) { | 237 if (!buffer) { |
| 234 LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: " | 238 LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: " |
| 235 "failed to GetByteArrayElements"; | 239 "failed to GetByteArrayElements"; |
| 236 return; | 240 return; |
| 237 } | 241 } |
| 238 | 242 |
| 239 const base::TimeTicks current_time = base::TimeTicks::Now(); | 243 const base::TimeTicks current_time = base::TimeTicks::Now(); |
| 240 if (!got_first_frame_) { | 244 if (!got_first_frame_) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 const tracked_objects::Location& from_here, | 372 const tracked_objects::Location& from_here, |
| 369 const std::string& reason) { | 373 const std::string& reason) { |
| 370 { | 374 { |
| 371 base::AutoLock lock(lock_); | 375 base::AutoLock lock(lock_); |
| 372 state_ = kError; | 376 state_ = kError; |
| 373 } | 377 } |
| 374 client_->OnError(from_here, reason); | 378 client_->OnError(from_here, reason); |
| 375 } | 379 } |
| 376 | 380 |
| 377 } // namespace media | 381 } // namespace media |
| OLD | NEW |