Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Side by Side Diff: media/capture/video/android/video_capture_device_android.cc

Issue 2983473002: Android Tango depth camera capture support.
Patch Set: rename tango_api files to tango_client_api_glue Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 } // anonymous namespace 97 } // anonymous namespace
98 98
99 // static 99 // static
100 bool VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice(JNIEnv* env) { 100 bool VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice(JNIEnv* env) {
101 return RegisterNativesImpl(env); 101 return RegisterNativesImpl(env);
102 } 102 }
103 103
104 VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid( 104 VideoCaptureDeviceAndroid::VideoCaptureDeviceAndroid(
105 const VideoCaptureDeviceDescriptor& device_descriptor) 105 const VideoCaptureDeviceDescriptor& device_descriptor)
106 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), 106 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
107 state_(kIdle),
108 got_first_frame_(false),
109 device_descriptor_(device_descriptor), 107 device_descriptor_(device_descriptor),
110 weak_ptr_factory_(this) {} 108 weak_ptr_factory_(this) {}
111 109
112 VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() { 110 VideoCaptureDeviceAndroid::~VideoCaptureDeviceAndroid() {
113 DCHECK(main_task_runner_->BelongsToCurrentThread()); 111 DCHECK(main_task_runner_->BelongsToCurrentThread());
114 StopAndDeAllocate(); 112 StopAndDeAllocate();
115 } 113 }
116 114
117 bool VideoCaptureDeviceAndroid::Init() { 115 bool VideoCaptureDeviceAndroid::Init() {
118 int id; 116 int id;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 } 253 }
256 DoSetPhotoOptions(std::move(settings), std::move(callback)); 254 DoSetPhotoOptions(std::move(settings), std::move(callback));
257 } 255 }
258 256
259 void VideoCaptureDeviceAndroid::OnFrameAvailable( 257 void VideoCaptureDeviceAndroid::OnFrameAvailable(
260 JNIEnv* env, 258 JNIEnv* env,
261 const JavaParamRef<jobject>& obj, 259 const JavaParamRef<jobject>& obj,
262 const JavaParamRef<jbyteArray>& data, 260 const JavaParamRef<jbyteArray>& data,
263 jint length, 261 jint length,
264 jint rotation) { 262 jint rotation) {
265 { 263 if (!IsClientConfiguredForIncomingData())
266 base::AutoLock lock(lock_); 264 return;
267 if (state_ != kConfigured || !client_)
268 return;
269 }
270
271 jbyte* buffer = env->GetByteArrayElements(data, NULL); 265 jbyte* buffer = env->GetByteArrayElements(data, NULL);
272 if (!buffer) { 266 if (!buffer) {
273 LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: " 267 LOG(ERROR) << "VideoCaptureDeviceAndroid::OnFrameAvailable: "
274 "failed to GetByteArrayElements"; 268 "failed to GetByteArrayElements";
275 return; 269 return;
276 } 270 }
277 271
278 const base::TimeTicks current_time = base::TimeTicks::Now(); 272 const base::TimeTicks current_time = base::TimeTicks::Now();
279 { 273 ProcessFirstFrameAvailable(current_time);
280 base::AutoLock lock(lock_);
281 if (!got_first_frame_) {
282 // Set aside one frame allowance for fluctuation.
283 expected_next_frame_time_ = current_time - frame_interval_;
284 got_first_frame_ = true;
285
286 for (const auto& request : photo_requests_queue_)
287 main_task_runner_->PostTask(FROM_HERE, request);
288 photo_requests_queue_.clear();
289 }
290 }
291 274
292 // Deliver the frame when it doesn't arrive too early. 275 // Deliver the frame when it doesn't arrive too early.
293 if (expected_next_frame_time_ <= current_time) { 276 if (expected_next_frame_time_ <= current_time) {
294 // Using |expected_next_frame_time_| to estimate a proper capture timestamp 277 // Using |expected_next_frame_time_| to estimate a proper capture timestamp
295 // since android.hardware.Camera API doesn't expose a better timestamp. 278 // since android.hardware.Camera API doesn't expose a better timestamp.
296 const base::TimeDelta capture_time = 279 const base::TimeDelta capture_time =
297 expected_next_frame_time_ - base::TimeTicks(); 280 expected_next_frame_time_ - base::TimeTicks();
298 281
299 expected_next_frame_time_ += frame_interval_; 282 expected_next_frame_time_ += frame_interval_;
300 283
301 // TODO(qiangchen): Investigate how to get raw timestamp for Android, 284 // TODO(qiangchen): Investigate how to get raw timestamp for Android,
302 // rather than using reference time to calculate timestamp. 285 // rather than using reference time to calculate timestamp.
303 base::AutoLock lock(lock_); 286 SendIncomingDataToClient(reinterpret_cast<uint8_t*>(buffer), length,
304 if (!client_) 287 rotation, current_time, capture_time);
305 return;
306 client_->OnIncomingCapturedData(reinterpret_cast<uint8_t*>(buffer), length,
307 capture_format_, rotation, current_time,
308 capture_time);
309 } 288 }
310 289
311 env->ReleaseByteArrayElements(data, buffer, JNI_ABORT); 290 env->ReleaseByteArrayElements(data, buffer, JNI_ABORT);
312 } 291 }
313 292
314 void VideoCaptureDeviceAndroid::OnI420FrameAvailable(JNIEnv* env, 293 void VideoCaptureDeviceAndroid::OnI420FrameAvailable(JNIEnv* env,
315 jobject obj, 294 jobject obj,
316 jobject y_buffer, 295 jobject y_buffer,
317 jint y_stride, 296 jint y_stride,
318 jobject u_buffer, 297 jobject u_buffer,
319 jobject v_buffer, 298 jobject v_buffer,
320 jint uv_row_stride, 299 jint uv_row_stride,
321 jint uv_pixel_stride, 300 jint uv_pixel_stride,
322 jint width, 301 jint width,
323 jint height, 302 jint height,
324 jint rotation, 303 jint rotation,
325 jlong timestamp) { 304 jlong timestamp) {
326 { 305 if (!IsClientConfiguredForIncomingData())
327 base::AutoLock lock(lock_); 306 return;
328 if (state_ != kConfigured || !client_)
329 return;
330 }
331 const int64_t absolute_micro = 307 const int64_t absolute_micro =
332 timestamp / base::Time::kNanosecondsPerMicrosecond; 308 timestamp / base::Time::kNanosecondsPerMicrosecond;
333 const base::TimeDelta capture_time = 309 const base::TimeDelta capture_time =
334 base::TimeDelta::FromMicroseconds(absolute_micro); 310 base::TimeDelta::FromMicroseconds(absolute_micro);
335 311
336 const base::TimeTicks current_time = base::TimeTicks::Now(); 312 const base::TimeTicks current_time = base::TimeTicks::Now();
337 { 313 ProcessFirstFrameAvailable(current_time);
338 base::AutoLock lock(lock_);
339 if (!got_first_frame_) {
340 // Set aside one frame allowance for fluctuation.
341 expected_next_frame_time_ = current_time - frame_interval_;
342 got_first_frame_ = true;
343
344 for (const auto& request : photo_requests_queue_)
345 main_task_runner_->PostTask(FROM_HERE, request);
346 photo_requests_queue_.clear();
347 }
348 }
349 314
350 uint8_t* const y_src = 315 uint8_t* const y_src =
351 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer)); 316 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(y_buffer));
352 CHECK(y_src); 317 CHECK(y_src);
353 uint8_t* const u_src = 318 uint8_t* const u_src =
354 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer)); 319 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(u_buffer));
355 CHECK(u_src); 320 CHECK(u_src);
356 uint8_t* const v_src = 321 uint8_t* const v_src =
357 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer)); 322 reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(v_buffer));
358 CHECK(v_src); 323 CHECK(v_src);
359 324
360 const int y_plane_length = width * height; 325 const int y_plane_length = width * height;
361 const int uv_plane_length = y_plane_length / 4; 326 const int uv_plane_length = y_plane_length / 4;
362 const int buffer_length = y_plane_length + uv_plane_length * 2; 327 const int buffer_length = y_plane_length + uv_plane_length * 2;
363 std::unique_ptr<uint8_t> buffer(new uint8_t[buffer_length]); 328 std::unique_ptr<uint8_t> buffer(new uint8_t[buffer_length]);
364 329
365 libyuv::Android420ToI420(y_src, y_stride, u_src, uv_row_stride, v_src, 330 libyuv::Android420ToI420(y_src, y_stride, u_src, uv_row_stride, v_src,
366 uv_row_stride, uv_pixel_stride, buffer.get(), width, 331 uv_row_stride, uv_pixel_stride, buffer.get(), width,
367 buffer.get() + y_plane_length, width / 2, 332 buffer.get() + y_plane_length, width / 2,
368 buffer.get() + y_plane_length + uv_plane_length, 333 buffer.get() + y_plane_length + uv_plane_length,
369 width / 2, width, height); 334 width / 2, width, height);
370 335
371 // Deliver the frame when it doesn't arrive too early. 336 // Deliver the frame when it doesn't arrive too early.
372 if (expected_next_frame_time_ <= current_time) { 337 if (AdvanceToNextFrameTime(current_time)) {
373 expected_next_frame_time_ += frame_interval_; 338 SendIncomingDataToClient(buffer.get(), buffer_length, rotation,
374 339 current_time, capture_time);
375 // TODO(qiangchen): Investigate how to get raw timestamp for Android,
376 // rather than using reference time to calculate timestamp.
377 base::AutoLock lock(lock_);
378 if (!client_)
379 return;
380 client_->OnIncomingCapturedData(buffer.get(), buffer_length,
381 capture_format_, rotation, current_time,
382 capture_time);
383 } 340 }
384 } 341 }
385 342
386 void VideoCaptureDeviceAndroid::OnError(JNIEnv* env, 343 void VideoCaptureDeviceAndroid::OnError(JNIEnv* env,
387 const JavaParamRef<jobject>& obj, 344 const JavaParamRef<jobject>& obj,
388 const JavaParamRef<jstring>& message) { 345 const JavaParamRef<jstring>& message) {
389 SetErrorState(FROM_HERE, 346 SetErrorState(FROM_HERE,
390 base::android::ConvertJavaStringToUTF8(env, message)); 347 base::android::ConvertJavaStringToUTF8(env, message));
391 } 348 }
392 349
(...skipping 30 matching lines...) Expand all
423 void VideoCaptureDeviceAndroid::OnStarted(JNIEnv* env, 380 void VideoCaptureDeviceAndroid::OnStarted(JNIEnv* env,
424 const JavaParamRef<jobject>& obj) { 381 const JavaParamRef<jobject>& obj) {
425 if (client_) 382 if (client_)
426 client_->OnStarted(); 383 client_->OnStarted();
427 } 384 }
428 385
429 void VideoCaptureDeviceAndroid::ConfigureForTesting() { 386 void VideoCaptureDeviceAndroid::ConfigureForTesting() {
430 Java_VideoCapture_setTestMode(AttachCurrentThread(), j_capture_); 387 Java_VideoCapture_setTestMode(AttachCurrentThread(), j_capture_);
431 } 388 }
432 389
390 void VideoCaptureDeviceAndroid::ProcessFirstFrameAvailable(
391 base::TimeTicks current_time) {
392 base::AutoLock lock(lock_);
393 if (got_first_frame_)
394 return;
395 // Set aside one frame allowance for fluctuation.
396 expected_next_frame_time_ = current_time - frame_interval_;
397 got_first_frame_ = true;
398
399 for (const auto& request : photo_requests_queue_)
400 main_task_runner_->PostTask(FROM_HERE, request);
401 photo_requests_queue_.clear();
402 }
403
404 bool VideoCaptureDeviceAndroid::IsClientConfiguredForIncomingData() {
405 base::AutoLock lock(lock_);
406 return (state_ == kConfigured && client_);
407 }
408
409 bool VideoCaptureDeviceAndroid::AdvanceToNextFrameTime(
410 base::TimeTicks current_time) {
411 if (expected_next_frame_time_ > current_time)
412 return false;
413 expected_next_frame_time_ += frame_interval_;
414 return true;
415 }
416
417 void VideoCaptureDeviceAndroid::SendIncomingDataToClient(
418 const uint8_t* data,
419 int length,
420 int rotation,
421 base::TimeTicks reference_time,
422 base::TimeDelta timestamp) {
423 base::AutoLock lock(lock_);
424 if (!client_)
425 return;
426 client_->OnIncomingCapturedData(data, length, capture_format_, rotation,
427 reference_time, timestamp);
428 }
429
433 VideoPixelFormat VideoCaptureDeviceAndroid::GetColorspace() { 430 VideoPixelFormat VideoCaptureDeviceAndroid::GetColorspace() {
434 JNIEnv* env = AttachCurrentThread(); 431 JNIEnv* env = AttachCurrentThread();
435 const int current_capture_colorspace = 432 const int current_capture_colorspace =
436 Java_VideoCapture_getColorspace(env, j_capture_); 433 Java_VideoCapture_getColorspace(env, j_capture_);
437 switch (current_capture_colorspace) { 434 switch (current_capture_colorspace) {
438 case ANDROID_IMAGE_FORMAT_YV12: 435 case ANDROID_IMAGE_FORMAT_YV12:
439 return media::PIXEL_FORMAT_YV12; 436 return media::PIXEL_FORMAT_YV12;
440 case ANDROID_IMAGE_FORMAT_YUV_420_888: 437 case ANDROID_IMAGE_FORMAT_YUV_420_888:
441 return media::PIXEL_FORMAT_I420; 438 return media::PIXEL_FORMAT_I420;
442 case ANDROID_IMAGE_FORMAT_NV21: 439 case ANDROID_IMAGE_FORMAT_NV21:
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 settings->has_exposure_compensation, exposure_compensation, 641 settings->has_exposure_compensation, exposure_compensation,
645 static_cast<int>(white_balance_mode), iso, 642 static_cast<int>(white_balance_mode), iso,
646 settings->has_red_eye_reduction, settings->red_eye_reduction, 643 settings->has_red_eye_reduction, settings->red_eye_reduction,
647 static_cast<int>(fill_light_mode), settings->has_torch, settings->torch, 644 static_cast<int>(fill_light_mode), settings->has_torch, settings->torch,
648 color_temperature); 645 color_temperature);
649 646
650 callback.Run(true); 647 callback.Run(true);
651 } 648 }
652 649
653 } // namespace media 650 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698