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

Side by Side Diff: media/capture/video/linux/v4l2_capture_delegate.cc

Issue 2344123002: ImageCapture: Implement TakePhoto() for Linux/CrOs (Closed)
Patch Set: Created 4 years, 3 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/linux/v4l2_capture_delegate.h" 5 #include "media/capture/video/linux/v4l2_capture_delegate.h"
6 6
7 #include <poll.h> 7 #include <poll.h>
8 #include <sys/fcntl.h> 8 #include <sys/fcntl.h>
9 #include <sys/ioctl.h> 9 #include <sys/ioctl.h>
10 #include <sys/mman.h> 10 #include <sys/mman.h>
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) 314 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0)
315 SetErrorState(FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0"); 315 SetErrorState(FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0");
316 316
317 // At this point we can close the device. 317 // At this point we can close the device.
318 // This is also needed for correctly changing settings later via VIDIOC_S_FMT. 318 // This is also needed for correctly changing settings later via VIDIOC_S_FMT.
319 device_fd_.reset(); 319 device_fd_.reset();
320 is_capturing_ = false; 320 is_capturing_ = false;
321 client_.reset(); 321 client_.reset();
322 } 322 }
323 323
324 void V4L2CaptureDelegate::TakePhoto(
325 VideoCaptureDevice::TakePhotoCallback callback) {
326 take_photo_callbacks_.push(std::move(callback));
mcasas 2016/09/16 03:50:36 nit: add DCHECK(v4l2_task_runner_->BelongsToCurren
xianglu 2016/09/16 18:22:33 Done.
327 DVLOG(1) << "in V4L2CaptureDelegate: callback moved";
mcasas 2016/09/16 03:50:36 nit: remove DVLOG()s when you submit for review,
xianglu 2016/09/16 18:22:33 Done.
328 }
329
324 void V4L2CaptureDelegate::SetRotation(int rotation) { 330 void V4L2CaptureDelegate::SetRotation(int rotation) {
325 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); 331 DCHECK(v4l2_task_runner_->BelongsToCurrentThread());
326 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); 332 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
327 rotation_ = rotation; 333 rotation_ = rotation;
328 } 334 }
329 335
330 V4L2CaptureDelegate::~V4L2CaptureDelegate() {} 336 V4L2CaptureDelegate::~V4L2CaptureDelegate() {}
331 337
332 bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) { 338 bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
333 v4l2_buffer buffer; 339 v4l2_buffer buffer;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 const scoped_refptr<BufferTracker>& buffer_tracker = 400 const scoped_refptr<BufferTracker>& buffer_tracker =
395 buffer_tracker_pool_[buffer.index]; 401 buffer_tracker_pool_[buffer.index];
396 402
397 base::TimeDelta timestamp = 403 base::TimeDelta timestamp =
398 base::TimeDelta::FromSeconds(buffer.timestamp.tv_sec) + 404 base::TimeDelta::FromSeconds(buffer.timestamp.tv_sec) +
399 base::TimeDelta::FromMicroseconds(buffer.timestamp.tv_usec); 405 base::TimeDelta::FromMicroseconds(buffer.timestamp.tv_usec);
400 client_->OnIncomingCapturedData( 406 client_->OnIncomingCapturedData(
401 buffer_tracker->start(), buffer_tracker->payload_size(), 407 buffer_tracker->start(), buffer_tracker->payload_size(),
402 capture_format_, rotation_, base::TimeTicks::Now(), timestamp); 408 capture_format_, rotation_, base::TimeTicks::Now(), timestamp);
403 409
410 // Process all the callbacks from TakePhoto()
mcasas 2016/09/16 03:50:36 nit: No need for this comment.
xianglu 2016/09/16 18:22:33 Done.
411 while (!take_photo_callbacks_.empty()) {
412 VideoCaptureDevice::TakePhotoCallback cb =
413 std::move(take_photo_callbacks_.front());
414 take_photo_callbacks_.pop();
415
416 if (mojom::BlobPtr blob = GetPhotoBlob(buffer_tracker, buffer))
mcasas 2016/09/16 03:50:36 nit: Don't mix assignments and conditionals.
xianglu 2016/09/16 18:22:33 Done.
417 cb.Run(std::move(blob));
418 else
419 DVLOG(3) << "blob pointer is null.";
420 }
421
404 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { 422 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
405 SetErrorState(FROM_HERE, "Failed to enqueue capture buffer"); 423 SetErrorState(FROM_HERE, "Failed to enqueue capture buffer");
406 return; 424 return;
407 } 425 }
408 } 426 }
409 427
410 v4l2_task_runner_->PostTask( 428 v4l2_task_runner_->PostTask(
411 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this)); 429 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this));
412 } 430 }
413 431
432 mojom::BlobPtr V4L2CaptureDelegate::GetPhotoBlob(
433 const scoped_refptr<BufferTracker>& buffer_tracker,
434 const v4l2_buffer& buffer) {
435 std::unique_ptr<uint8_t[]> dst_argb(new uint8_t[VideoFrame::AllocationSize(
436 PIXEL_FORMAT_ARGB, capture_format_.frame_size)]);
437 mojom::BlobPtr blob = mojom::Blob::New();
438
439 DVLOG(1) << "Format captured: "
440 << VideoPixelFormatToString(capture_format_.pixel_format);
441
442 uint32 src_format;
443 switch (capture_format_.pixel_format) {
444 case VideoPixelFormat::PIXEL_FORMAT_MJPEG:
445 blob->data.resize(buffer.bytesused);
mcasas 2016/09/16 03:50:36 If we take this path, |dst_argb| would be unused a
xianglu 2016/09/16 18:22:33 Indeed. Should work this way.
446 memcpy(blob->data.data(), buffer_tracker->start(), buffer.bytesused);
447 blob->mime_type = "image/jpeg";
448 return blob;
449 case VideoPixelFormat::PIXEL_FORMAT_UYVY:
450 src_format = libyuv::FOURCC_UYVY;
451 break;
452 case VideoPixelFormat::PIXEL_FORMAT_YUY2:
453 src_format = libyuv::FOURCC_YUY2;
454 break;
455 default:
456 DVLOG(3) << "FORMAT not supported.";
mcasas 2016/09/16 03:50:36 Instead of DVLOG(3), consider using DLOG(ERROR) <
xianglu 2016/09/16 18:22:33 Why would you remove ConvertFailure log?
mcasas 2016/09/16 18:59:15 All those error logs are only really useful for d
457 return nullptr;
458 }
459
460 if (ConvertToARGB(buffer_tracker->start(), buffer.bytesused, dst_argb.get(),
461 capture_format_.frame_size.width() * 4, 0 /* crop_x_pos */,
462 0 /* crop_y_pos */, capture_format_.frame_size.width(),
463 capture_format_.frame_size.height(),
464 capture_format_.frame_size.width(),
465 capture_format_.frame_size.height(),
466 libyuv::RotationMode::kRotate0, src_format) != 0) {
467 DVLOG(3) << "Failed to convert buffer's pixel format from "
468 << VideoPixelFormatToString(capture_format_.pixel_format)
469 << " to ARGB";
470 return nullptr;
471 }
472
473 const gfx::PNGCodec::ColorFormat codec_color_format =
474 (kN32_SkColorType == kRGBA_8888_SkColorType) ? gfx::PNGCodec::FORMAT_RGBA
475 : gfx::PNGCodec::FORMAT_BGRA;
476 const bool result = gfx::PNGCodec::Encode(
477 dst_argb.get(), codec_color_format, capture_format_.frame_size,
478 capture_format_.frame_size.width() * 4, true /* discard_transparency */,
479 std::vector<gfx::PNGCodec::Comment>(), &blob->data);
480 DCHECK(result);
481
482 blob->mime_type = "image/png";
483 return blob;
484 }
485
414 void V4L2CaptureDelegate::SetErrorState( 486 void V4L2CaptureDelegate::SetErrorState(
415 const tracked_objects::Location& from_here, 487 const tracked_objects::Location& from_here,
416 const std::string& reason) { 488 const std::string& reason) {
417 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); 489 DCHECK(v4l2_task_runner_->BelongsToCurrentThread());
418 is_capturing_ = false; 490 is_capturing_ = false;
419 client_->OnError(from_here, reason); 491 client_->OnError(from_here, reason);
420 } 492 }
421 493
422 V4L2CaptureDelegate::BufferTracker::BufferTracker() {} 494 V4L2CaptureDelegate::BufferTracker::BufferTracker() {}
423 495
(...skipping 14 matching lines...) Expand all
438 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; 510 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace";
439 return false; 511 return false;
440 } 512 }
441 start_ = static_cast<uint8_t*>(start); 513 start_ = static_cast<uint8_t*>(start);
442 length_ = buffer.length; 514 length_ = buffer.length;
443 payload_size_ = 0; 515 payload_size_ = 0;
444 return true; 516 return true;
445 } 517 }
446 518
447 } // namespace media 519 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698