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

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

Issue 2344123002: ImageCapture: Implement TakePhoto() for Linux/CrOs (Closed)
Patch Set: v4l2_capture_delegate.cc: GetPhotoBlob() use if/else to handle I420 and RGB24 format. 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>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/files/file_enumerator.h" 14 #include "base/files/file_enumerator.h"
15 #include "base/posix/eintr_wrapper.h" 15 #include "base/posix/eintr_wrapper.h"
16 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "build/build_config.h" 17 #include "build/build_config.h"
18 #include "media/base/bind_to_current_loop.h" 18 #include "media/base/bind_to_current_loop.h"
19 #include "media/capture/video/linux/video_capture_device_linux.h" 19 #include "media/capture/video/linux/video_capture_device_linux.h"
20 #include "third_party/libyuv/include/libyuv.h"
21 #include "third_party/skia/include/core/SkImage.h"
22 #include "ui/gfx/codec/png_codec.h"
20 23
21 namespace media { 24 namespace media {
22 25
23 // Desired number of video buffers to allocate. The actual number of allocated 26 // Desired number of video buffers to allocate. The actual number of allocated
24 // buffers by v4l2 driver can be higher or lower than this number. 27 // buffers by v4l2 driver can be higher or lower than this number.
25 // kNumVideoBuffers should not be too small, or Chrome may not return enough 28 // kNumVideoBuffers should not be too small, or Chrome may not return enough
26 // buffers back to driver in time. 29 // buffers back to driver in time.
27 const uint32_t kNumVideoBuffers = 4; 30 const uint32_t kNumVideoBuffers = 4;
28 // Timeout in milliseconds v4l2_thread_ blocks waiting for a frame from the hw. 31 // Timeout in milliseconds v4l2_thread_ blocks waiting for a frame from the hw.
29 // This value has been fine tuned. Before changing or modifying it see 32 // This value has been fine tuned. Before changing or modifying it see
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) 317 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0)
315 SetErrorState(FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0"); 318 SetErrorState(FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0");
316 319
317 // At this point we can close the device. 320 // At this point we can close the device.
318 // This is also needed for correctly changing settings later via VIDIOC_S_FMT. 321 // This is also needed for correctly changing settings later via VIDIOC_S_FMT.
319 device_fd_.reset(); 322 device_fd_.reset();
320 is_capturing_ = false; 323 is_capturing_ = false;
321 client_.reset(); 324 client_.reset();
322 } 325 }
323 326
327 void V4L2CaptureDelegate::TakePhoto(
328 VideoCaptureDevice::TakePhotoCallback callback) {
329 DCHECK(v4l2_task_runner_->BelongsToCurrentThread());
330 take_photo_callbacks_.push(std::move(callback));
331 }
332
324 void V4L2CaptureDelegate::SetRotation(int rotation) { 333 void V4L2CaptureDelegate::SetRotation(int rotation) {
325 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); 334 DCHECK(v4l2_task_runner_->BelongsToCurrentThread());
326 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0); 335 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
327 rotation_ = rotation; 336 rotation_ = rotation;
328 } 337 }
329 338
330 V4L2CaptureDelegate::~V4L2CaptureDelegate() {} 339 V4L2CaptureDelegate::~V4L2CaptureDelegate() {}
331 340
332 bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) { 341 bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
333 v4l2_buffer buffer; 342 v4l2_buffer buffer;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 const scoped_refptr<BufferTracker>& buffer_tracker = 403 const scoped_refptr<BufferTracker>& buffer_tracker =
395 buffer_tracker_pool_[buffer.index]; 404 buffer_tracker_pool_[buffer.index];
396 405
397 base::TimeDelta timestamp = 406 base::TimeDelta timestamp =
398 base::TimeDelta::FromSeconds(buffer.timestamp.tv_sec) + 407 base::TimeDelta::FromSeconds(buffer.timestamp.tv_sec) +
399 base::TimeDelta::FromMicroseconds(buffer.timestamp.tv_usec); 408 base::TimeDelta::FromMicroseconds(buffer.timestamp.tv_usec);
400 client_->OnIncomingCapturedData( 409 client_->OnIncomingCapturedData(
401 buffer_tracker->start(), buffer_tracker->payload_size(), 410 buffer_tracker->start(), buffer_tracker->payload_size(),
402 capture_format_, rotation_, base::TimeTicks::Now(), timestamp); 411 capture_format_, rotation_, base::TimeTicks::Now(), timestamp);
403 412
413 while (!take_photo_callbacks_.empty()) {
414 VideoCaptureDevice::TakePhotoCallback cb =
415 std::move(take_photo_callbacks_.front());
416 take_photo_callbacks_.pop();
417
418 mojom::BlobPtr blob = GetPhotoBlob(buffer_tracker, buffer);
419 if (blob)
420 cb.Run(std::move(blob));
421 else
422 DLOG(ERROR) << "blob pointer is null.";
mcasas 2016/09/16 21:17:07 Same reasoning as before, remove these two lines.
423 }
424
404 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { 425 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
405 SetErrorState(FROM_HERE, "Failed to enqueue capture buffer"); 426 SetErrorState(FROM_HERE, "Failed to enqueue capture buffer");
406 return; 427 return;
407 } 428 }
408 } 429 }
409 430
410 v4l2_task_runner_->PostTask( 431 v4l2_task_runner_->PostTask(
411 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this)); 432 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this));
412 } 433 }
413 434
435 mojom::BlobPtr V4L2CaptureDelegate::GetPhotoBlob(
436 const scoped_refptr<BufferTracker>& buffer_tracker,
437 const v4l2_buffer& buffer) {
mcasas 2016/09/16 21:17:06 We're only using buffer.bytesused, so pass that ui
438 uint32 src_format;
439
440 if (capture_format_.pixel_format == VideoPixelFormat::PIXEL_FORMAT_MJPEG) {
441 mojom::BlobPtr blob = mojom::Blob::New();
442 blob->data.resize(buffer.bytesused);
443 memcpy(blob->data.data(), buffer_tracker->start(), buffer.bytesused);
444 blob->mime_type = "image/jpeg";
445 return blob;
446 } else if (capture_format_.pixel_format ==
447 VideoPixelFormat::PIXEL_FORMAT_UYVY) {
448 src_format = libyuv::FOURCC_UYVY;
449 } else if (capture_format_.pixel_format ==
450 VideoPixelFormat::PIXEL_FORMAT_YUY2) {
451 src_format = libyuv::FOURCC_YUY2;
452 } else if (capture_format_.pixel_format ==
453 VideoPixelFormat::PIXEL_FORMAT_I420) {
454 src_format = libyuv::FOURCC_I420;
455 } else if (capture_format_.pixel_format ==
456 VideoPixelFormat::PIXEL_FORMAT_RGB24) {
457 src_format = libyuv::FOURCC_24BG;
458 } else {
459 return nullptr;
460 }
461
462 std::unique_ptr<uint8_t[]> dst_argb(new uint8_t[VideoFrame::AllocationSize(
463 PIXEL_FORMAT_ARGB, capture_format_.frame_size)]);
464 if (ConvertToARGB(buffer_tracker->start(), buffer.bytesused, dst_argb.get(),
465 capture_format_.frame_size.width() * 4, 0 /* crop_x_pos */,
466 0 /* crop_y_pos */, capture_format_.frame_size.width(),
467 capture_format_.frame_size.height(),
468 capture_format_.frame_size.width(),
469 capture_format_.frame_size.height(),
470 libyuv::RotationMode::kRotate0, src_format) != 0) {
471 return nullptr;
472 }
473
474 mojom::BlobPtr blob = mojom::Blob::New();
475 const gfx::PNGCodec::ColorFormat codec_color_format =
476 (kN32_SkColorType == kRGBA_8888_SkColorType) ? gfx::PNGCodec::FORMAT_RGBA
477 : gfx::PNGCodec::FORMAT_BGRA;
478 const bool result = gfx::PNGCodec::Encode(
479 dst_argb.get(), codec_color_format, capture_format_.frame_size,
480 capture_format_.frame_size.width() * 4, true /* discard_transparency */,
481 std::vector<gfx::PNGCodec::Comment>(), &blob->data);
482 DCHECK(result);
483
484 blob->mime_type = "image/png";
485 return blob;
486 }
487
414 void V4L2CaptureDelegate::SetErrorState( 488 void V4L2CaptureDelegate::SetErrorState(
415 const tracked_objects::Location& from_here, 489 const tracked_objects::Location& from_here,
416 const std::string& reason) { 490 const std::string& reason) {
417 DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); 491 DCHECK(v4l2_task_runner_->BelongsToCurrentThread());
418 is_capturing_ = false; 492 is_capturing_ = false;
419 client_->OnError(from_here, reason); 493 client_->OnError(from_here, reason);
420 } 494 }
421 495
422 V4L2CaptureDelegate::BufferTracker::BufferTracker() {} 496 V4L2CaptureDelegate::BufferTracker::BufferTracker() {}
423 497
(...skipping 14 matching lines...) Expand all
438 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; 512 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace";
439 return false; 513 return false;
440 } 514 }
441 start_ = static_cast<uint8_t*>(start); 515 start_ = static_cast<uint8_t*>(start);
442 length_ = buffer.length; 516 length_ = buffer.length;
443 payload_size_ = 0; 517 payload_size_ = 0;
444 return true; 518 return true;
445 } 519 }
446 520
447 } // namespace media 521 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/video/linux/v4l2_capture_delegate.h ('k') | media/capture/video/linux/video_capture_device_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698