Chromium Code Reviews| Index: media/video/capture/fake_video_capture_device.cc |
| diff --git a/media/video/capture/fake_video_capture_device.cc b/media/video/capture/fake_video_capture_device.cc |
| index a2cd37d65a035a6b1bab5000be54e57fe715205e..64e33a1d1e95b534511c89add38156d4d55ed701 100644 |
| --- a/media/video/capture/fake_video_capture_device.cc |
| +++ b/media/video/capture/fake_video_capture_device.cc |
| @@ -6,6 +6,14 @@ |
| #include <string> |
| +#if defined (OS_POSIX) |
| +#include <sys/fcntl.h> |
| +#include <sys/ioctl.h> |
| +#include <sys/mman.h> |
| +#include <drm/drm.h> |
| +#include <drm/drm_mode.h> |
| +#endif |
| + |
| #include "base/bind.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/strings/stringprintf.h" |
| @@ -15,10 +23,105 @@ |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkPaint.h" |
| +#if defined (OS_POSIX) |
| +#include "base/posix/eintr_wrapper.h" |
| +#endif |
| + |
| namespace media { |
| static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s. |
| +#if defined (OS_POSIX) |
| +class MmapedFile { |
|
emircan
2015/04/27 16:35:42
Mmapped or mmaped? They both sound wrong tbh.
|
| + public: |
| + MmapedFile(base::PlatformFile platform_file, size_t size) |
| + : platform_file_(platform_file), size_(size), data_(nullptr) { |
| + data_ = mmap(NULL, size_, PROT_READ | PROT_WRITE, MAP_SHARED, |
| + platform_file_, 0); |
| + DPLOG_IF(ERROR, data_ == MAP_FAILED) << "mmap() " << platform_file; |
| + } |
| + ~MmapedFile() { |
| + if (data_ != MAP_FAILED) |
| + munmap(data_, size_); |
| + } |
| + bool IsValid() const { return (data_ == MAP_FAILED); } |
| + void* data() const { return data_; } |
| + |
| + private: |
| + base::PlatformFile platform_file_; |
| + size_t size_; |
| + void* data_; |
| +}; |
| + |
| +class FakeVideoCaptureDevice::DrmDumbBuffer { |
| + public: |
| + explicit DrmDumbBuffer(const char* device_path); |
| + ~DrmDumbBuffer(); |
| + bool Init(media::VideoCaptureFormat format); |
| + void* Map(size_t size); |
| + |
| + private: |
| + base::ScopedFD drm_fd_; |
| + uint32 handle_; |
| +}; |
| + |
| +FakeVideoCaptureDevice::DrmDumbBuffer::DrmDumbBuffer(const char* device_path) |
| + : handle_(0) { |
| + drm_fd_.reset(HANDLE_EINTR(open(device_path, O_RDWR))); |
|
emircan
2015/04/27 16:35:42
I think we need the handle to dma_buf_fd conversio
mcasas
2015/05/07 15:59:45
Yeah we needed to jump through many hoops...
See a
|
| + DPLOG_IF(ERROR, !drm_fd_.is_valid()) |
| + << "Failed to open DRM device driver file."; |
| +} |
| + |
| +FakeVideoCaptureDevice::DrmDumbBuffer::~DrmDumbBuffer() { |
| + struct drm_mode_destroy_dumb creq = {}; |
| + creq.handle = handle_; |
| + if (HANDLE_EINTR(ioctl(drm_fd_.get(), DRM_IOCTL_MODE_DESTROY_DUMB, &creq)) < |
| + 0) { |
| + DPLOG(ERROR) << "Unable to Destroy DUMB buffer object"; |
| + } |
| +} |
| + |
| +bool FakeVideoCaptureDevice::DrmDumbBuffer::Init( |
| + media::VideoCaptureFormat format) { |
| + DCHECK_EQ(handle_, 0u); |
| + if (!drm_fd_.is_valid()) |
| + return false; |
| + |
| + struct drm_mode_create_dumb creq = {}; |
|
emircan
2015/04/27 16:35:42
memset(&creq, 0, sizeof(creq));
mcasas
2015/05/07 15:59:45
No need for that when using the = {} syntax
above
|
| + creq.width = format.frame_size.width(); |
| + creq.height = format.frame_size.height(); |
| + creq.bpp = 32; |
| + if (HANDLE_EINTR(ioctl(drm_fd_.get(), DRM_IOCTL_MODE_CREATE_DUMB, &creq)) |
| + < 0) { |
| + DPLOG(ERROR) << "Unable to create DUMB buffer object"; |
| + return false; |
| + } |
| + handle_ = creq.handle; |
| + DCHECK_GE(creq.size, format.frame_size.GetArea() * 4u); |
| + return true; |
| +} |
| + |
| +void* FakeVideoCaptureDevice::DrmDumbBuffer::Map(size_t size) { |
| + DCHECK_NE(handle_, 0u); |
| + if (!drm_fd_.is_valid()) |
| + return nullptr; |
| + |
| + struct drm_mode_map_dumb mreq ={}; |
| + mreq.handle = handle_; |
| + if (HANDLE_EINTR(ioctl(drm_fd_.get(), DRM_IOCTL_MODE_MAP_DUMB, &mreq)) < 0) { |
| + DPLOG(ERROR) << "Unable to Map DUMB buffer object"; |
| + return nullptr; |
| + } |
| + void* pixels = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, |
| + drm_fd_.get(), mreq.offset); |
| + if (pixels == MAP_FAILED) { |
| + DPLOG(ERROR) << "Unable to mmap() buffer object"; |
| + return nullptr; |
| + } |
| + return pixels; |
| +} |
| +#endif |
| + |
| void DrawPacman(bool use_argb, |
| uint8_t* const data, |
| int frame_count, |
| @@ -101,6 +204,11 @@ void FakeVideoCaptureDevice::AllocateAndStart( |
| else |
| capture_format_.frame_size.SetSize(320, 240); |
| +#if defined (OS_POSIX) |
| + drm_buffer_.reset(new DrmDumbBuffer("/dev/dri/card0")); |
| + drm_buffer_->Init(capture_format_); |
| +#endif |
| + |
| if (device_type_ == USING_OWN_BUFFERS || |
| device_type_ == USING_OWN_BUFFERS_TRIPLANAR) { |
| fake_frame_.reset(new uint8[VideoFrame::AllocationSize( |
| @@ -172,8 +280,20 @@ void FakeVideoCaptureDevice::CaptureUsingClientBuffers( |
| DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer"; |
| if (capture_buffer.get()) { |
| - uint8_t* const data_ptr = static_cast<uint8_t*>(capture_buffer->data()); |
| - DCHECK(data_ptr) << "Buffer has NO backing memory"; |
| + uint8_t* data_ptr = static_cast<uint8_t*>(capture_buffer->data()); |
| +#if defined (OS_POSIX) |
| + scoped_ptr<MmapedFile> mmaped_file; |
| + if (!data_ptr) { |
| + // Try mmap()ing the |capture_buffer| AsPlatformFile(). |
| + mmaped_file = make_scoped_ptr(new MmapedFile( |
| + capture_buffer->AsPlatformFile(), capture_buffer->size())); |
| + if (!mmaped_file->IsValid()) // Game Over |
| + return; |
| + data_ptr = static_cast<uint8*>(mmaped_file->data()); |
| + } |
| +#else |
| + DCHECK(data_ptr); |
| +#endif |
| memset(data_ptr, 0, capture_buffer->size()); |
| DrawPacman( |