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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/video/capture/fake_video_capture_device.h" 5 #include "media/video/capture/fake_video_capture_device.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #if defined(OS_CHROMEOS) && defined(USE_OZONE)
10 #include <errno.h>
11 #include <sys/fcntl.h>
12 #include <sys/mman.h>
13 #include <xf86drm.h>
14 #endif
15
9 #include "base/bind.h" 16 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
12 #include "media/audio/fake_audio_input_stream.h" 19 #include "media/audio/fake_audio_input_stream.h"
13 #include "media/base/video_frame.h" 20 #include "media/base/video_frame.h"
14 #include "third_party/skia/include/core/SkBitmap.h" 21 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "third_party/skia/include/core/SkCanvas.h" 22 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkPaint.h" 23 #include "third_party/skia/include/core/SkPaint.h"
17 24
25 #if defined(OS_CHROMEOS) && defined(USE_OZONE)
26 #include "base/files/file_enumerator.h"
27 #include "base/posix/eintr_wrapper.h"
28 #include "base/strings/string_util.h"
29 #endif
30
18 namespace media { 31 namespace media {
19 32
20 static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s. 33 static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s.
21 34
35 #if defined(OS_CHROMEOS) && defined(USE_OZONE)
36 static const char kVgemSysCardPath[] = "/sys/bus/platform/devices/vgem/drm/";
37 static const char kVgemDevDriCardPathFormat[] = "/dev/dri/card%d";
38
39 // Class to encapsulate opening the Vgem Fd and using it for mmap()ing and
40 // munmap()ing an incoming PrimeFd representing a Dma-Buf.
41 class FakeVideoCaptureDevice::VgemWrapper {
42 public:
43 VgemWrapper() {}
44 ~VgemWrapper() {}
45
46 // Finds out the /dev/dri/cardX associated with the Vgem, if any, and tries to
47 // open it. IsValid() tells if it has succeeded.
48 void Initialize();
49 bool IsValid() const { return vgem_fd_.is_valid(); }
50
51 // Tries to mmap() and incoming Dma-Buf PrimeFd into process space.
52 uint8* MmapPrimeFd(base::PlatformFile dma_buf_fd, size_t size);
53 // munmap()s the given |data_ptr| obtained from MmapPrimeFd().
54 void MunmapPointer(uint8* data_ptr, size_t size);
55
56 private:
57 base::ScopedFD vgem_fd_;
58 };
59
60 void FakeVideoCaptureDevice::VgemWrapper::Initialize() {
61 // VGEM fd is a /dev/dri device but we cannot know in advance which one, for
62 // that we inspect the /sys/.../vgem/.../cardX, if we find one such card, then
63 // VGEM is present in the system and we can reuse the index.
64 base::FileEnumerator file_iter(
65 base::FilePath::FromUTF8Unsafe(kVgemSysCardPath),
66 true,
67 base::FileEnumerator::FILES,
dshwang 2015/05/12 12:58:44 false, base::FileEnumerator::DIRECTORIES, I use t
68 FILE_PATH_LITERAL("card*"));
69
70 while (!file_iter.Next().empty()) {
71 // Inspect the card%d files in the directory, if any. Extract the index.
72 DVLOG(1) << file_iter.GetInfo().GetName().BaseName().MaybeAsASCII();
73 std::string name(file_iter.GetInfo().GetName().BaseName().MaybeAsASCII());
74 base::TrimString(name, "card", &name);
75 errno = 0;
76 const int device_index = strtol(name.c_str(), NULL, 10);
77 DLOG_IF(ERROR, errno != 0) << "Error extracting integer from " << name;
78 if (errno != 0)
79 return;
80
81 const base::FilePath vgem_path = base::FilePath(
82 base::StringPrintf(kVgemDevDriCardPathFormat, device_index));
83 DVLOG(1) << "possible Vgem fd is " << vgem_path.MaybeAsASCII();
84
85 vgem_fd_.reset(
86 HANDLE_EINTR(open(vgem_path.MaybeAsASCII().c_str(), O_RDWR)));
87 if (vgem_fd_.is_valid()) {
88 DVLOG(1) << "Opened Vgem file " << vgem_path.MaybeAsASCII();
89 return;
90 }
91 DLOG(ERROR) << "Failed to open vgem device driver file "
92 << vgem_path.MaybeAsASCII();
93 }
94 }
95
96 uint8* FakeVideoCaptureDevice::VgemWrapper::MmapPrimeFd(
97 base::PlatformFile dma_buf_fd,
98 size_t size) {
99 uint32_t foreign_imported_handle;
100 int result = drmPrimeFDToHandle(vgem_fd_.get(),
101 dma_buf_fd,
102 &foreign_imported_handle);
103 if (result) {
104 DLOG(ERROR) << "Error mapping PrimeFd to Handle";
105 return nullptr;
106 }
107
108 struct drm_mode_map_dumb mmap_arg = {};
109 mmap_arg.handle = foreign_imported_handle;
110 result = drmIoctl(vgem_fd_.get(),
111 DRM_IOCTL_MODE_MAP_DUMB,
112 &mmap_arg);
113 if (result || (mmap_arg.offset == 0u)) {
114 DLOG(ERROR) << "Error preparing Handle to be mmap()ed";
115 return nullptr;
116 }
117
118 void* data_ptr = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED,
119 vgem_fd_.get(), mmap_arg.offset);
120 if (data_ptr == MAP_FAILED) {
121 DLOG(ERROR) << "Error mmap()ing the dma-buf into userspace";
122 return nullptr;
123 }
124 return static_cast<uint8*>(data_ptr);
125 }
126
127 void FakeVideoCaptureDevice::VgemWrapper::MunmapPointer(
128 uint8* data_ptr, size_t size) {
129 munmap(data_ptr, size);
130 }
131 #endif
132
22 void DrawPacman(bool use_argb, 133 void DrawPacman(bool use_argb,
23 uint8_t* const data, 134 uint8_t* const data,
24 int frame_count, 135 int frame_count,
25 int frame_interval, 136 int frame_interval,
26 const gfx::Size& frame_size) { 137 const gfx::Size& frame_size) {
27 // |kN32_SkColorType| stands for the appropriiate RGBA/BGRA format. 138 // |kN32_SkColorType| stands for the appropriiate RGBA/BGRA format.
28 const SkColorType colorspace = 139 const SkColorType colorspace =
29 use_argb ? kN32_SkColorType : kAlpha_8_SkColorType; 140 use_argb ? kN32_SkColorType : kAlpha_8_SkColorType;
30 const SkImageInfo info = SkImageInfo::Make(frame_size.width(), 141 const SkImageInfo info = SkImageInfo::Make(frame_size.width(),
31 frame_size.height(), 142 frame_size.height(),
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 capture_format_.frame_rate = 30.0; 205 capture_format_.frame_rate = 30.0;
95 if (params.requested_format.frame_size.width() > 1280) 206 if (params.requested_format.frame_size.width() > 1280)
96 capture_format_.frame_size.SetSize(1920, 1080); 207 capture_format_.frame_size.SetSize(1920, 1080);
97 else if (params.requested_format.frame_size.width() > 640) 208 else if (params.requested_format.frame_size.width() > 640)
98 capture_format_.frame_size.SetSize(1280, 720); 209 capture_format_.frame_size.SetSize(1280, 720);
99 else if (params.requested_format.frame_size.width() > 320) 210 else if (params.requested_format.frame_size.width() > 320)
100 capture_format_.frame_size.SetSize(640, 480); 211 capture_format_.frame_size.SetSize(640, 480);
101 else 212 else
102 capture_format_.frame_size.SetSize(320, 240); 213 capture_format_.frame_size.SetSize(320, 240);
103 214
215 #if defined(OS_CHROMEOS) && defined(USE_OZONE)
216 vgem_wrapper_.reset(new VgemWrapper());
217 vgem_wrapper_->Initialize();
218 #endif
219
104 if (device_type_ == USING_OWN_BUFFERS || 220 if (device_type_ == USING_OWN_BUFFERS ||
105 device_type_ == USING_OWN_BUFFERS_TRIPLANAR) { 221 device_type_ == USING_OWN_BUFFERS_TRIPLANAR) {
106 fake_frame_.reset(new uint8[VideoFrame::AllocationSize( 222 fake_frame_.reset(new uint8[VideoFrame::AllocationSize(
107 VideoFrame::I420, capture_format_.frame_size)]); 223 VideoFrame::I420, capture_format_.frame_size)]);
108 BeepAndScheduleNextCapture( 224 BeepAndScheduleNextCapture(
109 base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers, 225 base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers,
110 weak_factory_.GetWeakPtr())); 226 weak_factory_.GetWeakPtr()));
111 } else if (device_type_ == USING_CLIENT_BUFFERS_I420 || 227 } else if (device_type_ == USING_CLIENT_BUFFERS_I420 ||
112 device_type_ == USING_CLIENT_BUFFERS_GPU) { 228 device_type_ == USING_CLIENT_BUFFERS_GPU) {
113 DVLOG(1) << "starting with " << (device_type_ == USING_CLIENT_BUFFERS_I420 229 DVLOG(1) << "starting with " << (device_type_ == USING_CLIENT_BUFFERS_I420
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 281
166 void FakeVideoCaptureDevice::CaptureUsingClientBuffers( 282 void FakeVideoCaptureDevice::CaptureUsingClientBuffers(
167 VideoPixelFormat pixel_format) { 283 VideoPixelFormat pixel_format) {
168 DCHECK(thread_checker_.CalledOnValidThread()); 284 DCHECK(thread_checker_.CalledOnValidThread());
169 285
170 scoped_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer( 286 scoped_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer(
171 client_->ReserveOutputBuffer(pixel_format, capture_format_.frame_size)); 287 client_->ReserveOutputBuffer(pixel_format, capture_format_.frame_size));
172 DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer"; 288 DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer";
173 289
174 if (capture_buffer.get()) { 290 if (capture_buffer.get()) {
175 uint8_t* const data_ptr = static_cast<uint8_t*>(capture_buffer->data()); 291 uint8_t* data_ptr = static_cast<uint8_t*>(capture_buffer->data());
176 DCHECK(data_ptr) << "Buffer has NO backing memory"; 292
177 DCHECK_EQ(capture_buffer->GetType(), gfx::SHARED_MEMORY_BUFFER); 293 #if defined(OS_CHROMEOS) && defined(USE_OZONE)
294 if (!data_ptr && vgem_wrapper_->IsValid()) {
295 data_ptr = vgem_wrapper_->MmapPrimeFd(capture_buffer->AsPlatformFile(),
296 capture_buffer->size());
297 }
298 #endif
299 DCHECK(data_ptr);
178 memset(data_ptr, 0, capture_buffer->size()); 300 memset(data_ptr, 0, capture_buffer->size());
179 301
180 DrawPacman( 302 DrawPacman(
181 (pixel_format == media::PIXEL_FORMAT_GPUMEMORYBUFFER), /* use_argb */ 303 (pixel_format == media::PIXEL_FORMAT_GPUMEMORYBUFFER), /* use_argb */
182 data_ptr, 304 data_ptr,
183 frame_count_, 305 frame_count_,
184 kFakeCapturePeriodMs, 306 kFakeCapturePeriodMs,
185 capture_format_.frame_size); 307 capture_format_.frame_size);
186 308
187 // Give the captured frame to the client. 309 // Give the captured frame to the client.
188 const VideoCaptureFormat format(capture_format_.frame_size, 310 const VideoCaptureFormat format(capture_format_.frame_size,
189 capture_format_.frame_rate, 311 capture_format_.frame_rate,
190 pixel_format); 312 pixel_format);
191 client_->OnIncomingCapturedBuffer(capture_buffer.Pass(), format, 313 client_->OnIncomingCapturedBuffer(capture_buffer.Pass(), format,
192 base::TimeTicks::Now()); 314 base::TimeTicks::Now());
315 #if defined(OS_CHROMEOS) && defined(USE_OZONE)
316 if (vgem_wrapper_->IsValid())
317 vgem_wrapper_->MunmapPointer(data_ptr, capture_buffer->size());
318 #endif
193 } 319 }
194 320
195 BeepAndScheduleNextCapture( 321 BeepAndScheduleNextCapture(
196 base::Bind(&FakeVideoCaptureDevice::CaptureUsingClientBuffers, 322 base::Bind(&FakeVideoCaptureDevice::CaptureUsingClientBuffers,
197 weak_factory_.GetWeakPtr(), pixel_format)); 323 weak_factory_.GetWeakPtr(), pixel_format));
198 } 324 }
199 325
200 void FakeVideoCaptureDevice::BeepAndScheduleNextCapture( 326 void FakeVideoCaptureDevice::BeepAndScheduleNextCapture(
201 const base::Closure& next_capture) { 327 const base::Closure& next_capture) {
202 // Generate a synchronized beep sound every so many frames. 328 // Generate a synchronized beep sound every so many frames.
203 if (frame_count_++ % kFakeCaptureBeepCycle == 0) 329 if (frame_count_++ % kFakeCaptureBeepCycle == 0)
204 FakeAudioInputStream::BeepOnce(); 330 FakeAudioInputStream::BeepOnce();
205 331
206 // Reschedule next CaptureTask. 332 // Reschedule next CaptureTask.
207 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, next_capture, 333 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, next_capture,
208 base::TimeDelta::FromMilliseconds(kFakeCapturePeriodMs)); 334 base::TimeDelta::FromMilliseconds(kFakeCapturePeriodMs));
209 } 335 }
210 336
211 } // namespace media 337 } // namespace media
OLDNEW
« 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