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( |