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 3279e54ef1bca9c2c564f76427c453abed4cb45c..aae3b8a40819ffbe7fffa8272e1cc6f7cbab617f 100644 |
| --- a/media/video/capture/fake_video_capture_device.cc |
| +++ b/media/video/capture/fake_video_capture_device.cc |
| @@ -6,6 +6,13 @@ |
| #include <string> |
| +#if defined(OS_CHROMEOS) && defined(USE_OZONE) |
| +#include <errno.h> |
| +#include <sys/fcntl.h> |
| +#include <sys/mman.h> |
| +#include <xf86drm.h> |
| +#endif |
| + |
| #include "base/bind.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/strings/stringprintf.h" |
| @@ -15,10 +22,114 @@ |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkPaint.h" |
| +#if defined(OS_CHROMEOS) && defined(USE_OZONE) |
| +#include "base/files/file_enumerator.h" |
| +#include "base/posix/eintr_wrapper.h" |
| +#include "base/strings/string_util.h" |
| +#endif |
| + |
| namespace media { |
| static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s. |
| +#if defined(OS_CHROMEOS) && defined(USE_OZONE) |
| +static const char kVgemSysCardPath[] = "/sys/bus/platform/devices/vgem/drm/"; |
| +static const char kVgemDevDriCardPathFormat[] = "/dev/dri/card%d"; |
| + |
| +// Class to encapsulate opening the Vgem Fd and using it for mmap()ing and |
| +// munmap()ing an incoming PrimeFd representing a Dma-Buf. |
| +class FakeVideoCaptureDevice::VgemWrapper { |
| + public: |
| + VgemWrapper() {} |
| + ~VgemWrapper() {} |
| + |
| + // Finds out the /dev/dri/cardX associated with the Vgem, if any, and tries to |
| + // open it. IsValid() tells if it has succeeded. |
| + void Initialize(); |
| + bool IsValid() const { return vgem_fd_.is_valid(); } |
| + |
| + // Tries to mmap() and incoming Dma-Buf PrimeFd into process space. |
| + uint8* MmapPrimeFd(base::PlatformFile dma_buf_fd, size_t size); |
| + // munmap()s the given |data_ptr| obtained from MmapPrimeFd(). |
| + void MunmapPointer(uint8* data_ptr, size_t size); |
| + |
| + private: |
| + base::ScopedFD vgem_fd_; |
| +}; |
| + |
| +void FakeVideoCaptureDevice::VgemWrapper::Initialize() { |
| + // VGEM fd is a /dev/dri device but we cannot know in advance which one, for |
| + // that we inspect the /sys/.../vgem/.../cardX, if we find one such card, then |
| + // VGEM is present in the system and we can reuse the index. |
| + base::FileEnumerator file_iter( |
| + base::FilePath::FromUTF8Unsafe(kVgemSysCardPath), |
| + true, |
| + base::FileEnumerator::FILES, |
|
dshwang
2015/05/12 12:58:44
false, base::FileEnumerator::DIRECTORIES,
I use t
|
| + FILE_PATH_LITERAL("card*")); |
| + |
| + while (!file_iter.Next().empty()) { |
| + // Inspect the card%d files in the directory, if any. Extract the index. |
| + DVLOG(1) << file_iter.GetInfo().GetName().BaseName().MaybeAsASCII(); |
| + std::string name(file_iter.GetInfo().GetName().BaseName().MaybeAsASCII()); |
| + base::TrimString(name, "card", &name); |
| + errno = 0; |
| + const int device_index = strtol(name.c_str(), NULL, 10); |
| + DLOG_IF(ERROR, errno != 0) << "Error extracting integer from " << name; |
| + if (errno != 0) |
| + return; |
| + |
| + const base::FilePath vgem_path = base::FilePath( |
| + base::StringPrintf(kVgemDevDriCardPathFormat, device_index)); |
| + DVLOG(1) << "possible Vgem fd is " << vgem_path.MaybeAsASCII(); |
| + |
| + vgem_fd_.reset( |
| + HANDLE_EINTR(open(vgem_path.MaybeAsASCII().c_str(), O_RDWR))); |
| + if (vgem_fd_.is_valid()) { |
| + DVLOG(1) << "Opened Vgem file " << vgem_path.MaybeAsASCII(); |
| + return; |
| + } |
| + DLOG(ERROR) << "Failed to open vgem device driver file " |
| + << vgem_path.MaybeAsASCII(); |
| + } |
| +} |
| + |
| +uint8* FakeVideoCaptureDevice::VgemWrapper::MmapPrimeFd( |
| + base::PlatformFile dma_buf_fd, |
| + size_t size) { |
| + uint32_t foreign_imported_handle; |
| + int result = drmPrimeFDToHandle(vgem_fd_.get(), |
| + dma_buf_fd, |
| + &foreign_imported_handle); |
| + if (result) { |
| + DLOG(ERROR) << "Error mapping PrimeFd to Handle"; |
| + return nullptr; |
| + } |
| + |
| + struct drm_mode_map_dumb mmap_arg = {}; |
| + mmap_arg.handle = foreign_imported_handle; |
| + result = drmIoctl(vgem_fd_.get(), |
| + DRM_IOCTL_MODE_MAP_DUMB, |
| + &mmap_arg); |
| + if (result || (mmap_arg.offset == 0u)) { |
| + DLOG(ERROR) << "Error preparing Handle to be mmap()ed"; |
| + return nullptr; |
| + } |
| + |
| + void* data_ptr = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, |
| + vgem_fd_.get(), mmap_arg.offset); |
| + if (data_ptr == MAP_FAILED) { |
| + DLOG(ERROR) << "Error mmap()ing the dma-buf into userspace"; |
| + return nullptr; |
| + } |
| + return static_cast<uint8*>(data_ptr); |
| +} |
| + |
| +void FakeVideoCaptureDevice::VgemWrapper::MunmapPointer( |
| + uint8* data_ptr, size_t size) { |
| + munmap(data_ptr, size); |
| +} |
| +#endif |
| + |
| void DrawPacman(bool use_argb, |
| uint8_t* const data, |
| int frame_count, |
| @@ -101,6 +212,11 @@ void FakeVideoCaptureDevice::AllocateAndStart( |
| else |
| capture_format_.frame_size.SetSize(320, 240); |
| +#if defined(OS_CHROMEOS) && defined(USE_OZONE) |
| + vgem_wrapper_.reset(new VgemWrapper()); |
| + vgem_wrapper_->Initialize(); |
| +#endif |
| + |
| if (device_type_ == USING_OWN_BUFFERS || |
| device_type_ == USING_OWN_BUFFERS_TRIPLANAR) { |
| fake_frame_.reset(new uint8[VideoFrame::AllocationSize( |
| @@ -172,9 +288,15 @@ 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"; |
| - DCHECK_EQ(capture_buffer->GetType(), gfx::SHARED_MEMORY_BUFFER); |
| + uint8_t* data_ptr = static_cast<uint8_t*>(capture_buffer->data()); |
| + |
| +#if defined(OS_CHROMEOS) && defined(USE_OZONE) |
| + if (!data_ptr && vgem_wrapper_->IsValid()) { |
| + data_ptr = vgem_wrapper_->MmapPrimeFd(capture_buffer->AsPlatformFile(), |
| + capture_buffer->size()); |
| + } |
| +#endif |
| + DCHECK(data_ptr); |
| memset(data_ptr, 0, capture_buffer->size()); |
| DrawPacman( |
| @@ -190,6 +312,10 @@ void FakeVideoCaptureDevice::CaptureUsingClientBuffers( |
| pixel_format); |
| client_->OnIncomingCapturedBuffer(capture_buffer.Pass(), format, |
| base::TimeTicks::Now()); |
| +#if defined(OS_CHROMEOS) && defined(USE_OZONE) |
| + if (vgem_wrapper_->IsValid()) |
| + vgem_wrapper_->MunmapPointer(data_ptr, capture_buffer->size()); |
| +#endif |
| } |
| BeepAndScheduleNextCapture( |