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

Unified Diff: media/video/capture/fake_video_capture_device.cc

Issue 1106563002: FakeVideoCaptureDevice: add support for capturing into Dma-Bufs using VGEM in CrOs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: ermircan@ comments; removed GpuMemoryBuffer modifications (go in other CL) Created 5 years, 7 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 side-by-side diff with in-line comments
Download patch
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(
« no previous file with comments | « media/video/capture/fake_video_capture_device.h ('k') | media/video/capture/fake_video_capture_device_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698