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

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: Created 5 years, 8 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_POSIX)
10 #include <sys/fcntl.h>
11 #include <sys/ioctl.h>
12 #include <sys/mman.h>
13 #include <drm/drm.h>
14 #include <drm/drm_mode.h>
15 #endif
16
9 #include "base/bind.h" 17 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h" 18 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
12 #include "media/audio/fake_audio_input_stream.h" 20 #include "media/audio/fake_audio_input_stream.h"
13 #include "media/base/video_frame.h" 21 #include "media/base/video_frame.h"
14 #include "third_party/skia/include/core/SkBitmap.h" 22 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "third_party/skia/include/core/SkCanvas.h" 23 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkPaint.h" 24 #include "third_party/skia/include/core/SkPaint.h"
17 25
26 #if defined (OS_POSIX)
27 #include "base/posix/eintr_wrapper.h"
28 #endif
29
18 namespace media { 30 namespace media {
19 31
20 static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s. 32 static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s.
21 33
34 #if defined (OS_POSIX)
35 class MmapedFile {
emircan 2015/04/27 16:35:42 Mmapped or mmaped? They both sound wrong tbh.
36 public:
37 MmapedFile(base::PlatformFile platform_file, size_t size)
38 : platform_file_(platform_file), size_(size), data_(nullptr) {
39 data_ = mmap(NULL, size_, PROT_READ | PROT_WRITE, MAP_SHARED,
40 platform_file_, 0);
41 DPLOG_IF(ERROR, data_ == MAP_FAILED) << "mmap() " << platform_file;
42 }
43 ~MmapedFile() {
44 if (data_ != MAP_FAILED)
45 munmap(data_, size_);
46 }
47 bool IsValid() const { return (data_ == MAP_FAILED); }
48 void* data() const { return data_; }
49
50 private:
51 base::PlatformFile platform_file_;
52 size_t size_;
53 void* data_;
54 };
55
56 class FakeVideoCaptureDevice::DrmDumbBuffer {
57 public:
58 explicit DrmDumbBuffer(const char* device_path);
59 ~DrmDumbBuffer();
60 bool Init(media::VideoCaptureFormat format);
61 void* Map(size_t size);
62
63 private:
64 base::ScopedFD drm_fd_;
65 uint32 handle_;
66 };
67
68 FakeVideoCaptureDevice::DrmDumbBuffer::DrmDumbBuffer(const char* device_path)
69 : handle_(0) {
70 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
71 DPLOG_IF(ERROR, !drm_fd_.is_valid())
72 << "Failed to open DRM device driver file.";
73 }
74
75 FakeVideoCaptureDevice::DrmDumbBuffer::~DrmDumbBuffer() {
76 struct drm_mode_destroy_dumb creq = {};
77 creq.handle = handle_;
78 if (HANDLE_EINTR(ioctl(drm_fd_.get(), DRM_IOCTL_MODE_DESTROY_DUMB, &creq)) <
79 0) {
80 DPLOG(ERROR) << "Unable to Destroy DUMB buffer object";
81 }
82 }
83
84 bool FakeVideoCaptureDevice::DrmDumbBuffer::Init(
85 media::VideoCaptureFormat format) {
86 DCHECK_EQ(handle_, 0u);
87 if (!drm_fd_.is_valid())
88 return false;
89
90 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
91 creq.width = format.frame_size.width();
92 creq.height = format.frame_size.height();
93 creq.bpp = 32;
94 if (HANDLE_EINTR(ioctl(drm_fd_.get(), DRM_IOCTL_MODE_CREATE_DUMB, &creq))
95 < 0) {
96 DPLOG(ERROR) << "Unable to create DUMB buffer object";
97 return false;
98 }
99 handle_ = creq.handle;
100 DCHECK_GE(creq.size, format.frame_size.GetArea() * 4u);
101 return true;
102 }
103
104 void* FakeVideoCaptureDevice::DrmDumbBuffer::Map(size_t size) {
105 DCHECK_NE(handle_, 0u);
106 if (!drm_fd_.is_valid())
107 return nullptr;
108
109 struct drm_mode_map_dumb mreq ={};
110 mreq.handle = handle_;
111 if (HANDLE_EINTR(ioctl(drm_fd_.get(), DRM_IOCTL_MODE_MAP_DUMB, &mreq)) < 0) {
112 DPLOG(ERROR) << "Unable to Map DUMB buffer object";
113 return nullptr;
114 }
115 void* pixels = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED,
116 drm_fd_.get(), mreq.offset);
117 if (pixels == MAP_FAILED) {
118 DPLOG(ERROR) << "Unable to mmap() buffer object";
119 return nullptr;
120 }
121 return pixels;
122 }
123 #endif
124
22 void DrawPacman(bool use_argb, 125 void DrawPacman(bool use_argb,
23 uint8_t* const data, 126 uint8_t* const data,
24 int frame_count, 127 int frame_count,
25 int frame_interval, 128 int frame_interval,
26 const gfx::Size& frame_size) { 129 const gfx::Size& frame_size) {
27 // |kN32_SkColorType| stands for the appropriiate RGBA/BGRA format. 130 // |kN32_SkColorType| stands for the appropriiate RGBA/BGRA format.
28 const SkColorType colorspace = 131 const SkColorType colorspace =
29 use_argb ? kN32_SkColorType : kAlpha_8_SkColorType; 132 use_argb ? kN32_SkColorType : kAlpha_8_SkColorType;
30 const SkImageInfo info = SkImageInfo::Make(frame_size.width(), 133 const SkImageInfo info = SkImageInfo::Make(frame_size.width(),
31 frame_size.height(), 134 frame_size.height(),
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 capture_format_.frame_rate = 30.0; 197 capture_format_.frame_rate = 30.0;
95 if (params.requested_format.frame_size.width() > 1280) 198 if (params.requested_format.frame_size.width() > 1280)
96 capture_format_.frame_size.SetSize(1920, 1080); 199 capture_format_.frame_size.SetSize(1920, 1080);
97 else if (params.requested_format.frame_size.width() > 640) 200 else if (params.requested_format.frame_size.width() > 640)
98 capture_format_.frame_size.SetSize(1280, 720); 201 capture_format_.frame_size.SetSize(1280, 720);
99 else if (params.requested_format.frame_size.width() > 320) 202 else if (params.requested_format.frame_size.width() > 320)
100 capture_format_.frame_size.SetSize(640, 480); 203 capture_format_.frame_size.SetSize(640, 480);
101 else 204 else
102 capture_format_.frame_size.SetSize(320, 240); 205 capture_format_.frame_size.SetSize(320, 240);
103 206
207 #if defined (OS_POSIX)
208 drm_buffer_.reset(new DrmDumbBuffer("/dev/dri/card0"));
209 drm_buffer_->Init(capture_format_);
210 #endif
211
104 if (device_type_ == USING_OWN_BUFFERS || 212 if (device_type_ == USING_OWN_BUFFERS ||
105 device_type_ == USING_OWN_BUFFERS_TRIPLANAR) { 213 device_type_ == USING_OWN_BUFFERS_TRIPLANAR) {
106 fake_frame_.reset(new uint8[VideoFrame::AllocationSize( 214 fake_frame_.reset(new uint8[VideoFrame::AllocationSize(
107 VideoFrame::I420, capture_format_.frame_size)]); 215 VideoFrame::I420, capture_format_.frame_size)]);
108 BeepAndScheduleNextCapture( 216 BeepAndScheduleNextCapture(
109 base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers, 217 base::Bind(&FakeVideoCaptureDevice::CaptureUsingOwnBuffers,
110 weak_factory_.GetWeakPtr())); 218 weak_factory_.GetWeakPtr()));
111 } else if (device_type_ == USING_CLIENT_BUFFERS_I420 || 219 } else if (device_type_ == USING_CLIENT_BUFFERS_I420 ||
112 device_type_ == USING_CLIENT_BUFFERS_GPU) { 220 device_type_ == USING_CLIENT_BUFFERS_GPU) {
113 DVLOG(1) << "starting with " << (device_type_ == USING_CLIENT_BUFFERS_I420 221 DVLOG(1) << "starting with " << (device_type_ == USING_CLIENT_BUFFERS_I420
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 273
166 void FakeVideoCaptureDevice::CaptureUsingClientBuffers( 274 void FakeVideoCaptureDevice::CaptureUsingClientBuffers(
167 VideoPixelFormat pixel_format) { 275 VideoPixelFormat pixel_format) {
168 DCHECK(thread_checker_.CalledOnValidThread()); 276 DCHECK(thread_checker_.CalledOnValidThread());
169 277
170 scoped_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer( 278 scoped_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer(
171 client_->ReserveOutputBuffer(pixel_format, capture_format_.frame_size)); 279 client_->ReserveOutputBuffer(pixel_format, capture_format_.frame_size));
172 DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer"; 280 DLOG_IF(ERROR, !capture_buffer) << "Couldn't allocate Capture Buffer";
173 281
174 if (capture_buffer.get()) { 282 if (capture_buffer.get()) {
175 uint8_t* const data_ptr = static_cast<uint8_t*>(capture_buffer->data()); 283 uint8_t* data_ptr = static_cast<uint8_t*>(capture_buffer->data());
176 DCHECK(data_ptr) << "Buffer has NO backing memory"; 284 #if defined (OS_POSIX)
285 scoped_ptr<MmapedFile> mmaped_file;
286 if (!data_ptr) {
287 // Try mmap()ing the |capture_buffer| AsPlatformFile().
288 mmaped_file = make_scoped_ptr(new MmapedFile(
289 capture_buffer->AsPlatformFile(), capture_buffer->size()));
290 if (!mmaped_file->IsValid()) // Game Over
291 return;
292 data_ptr = static_cast<uint8*>(mmaped_file->data());
293 }
294 #else
295 DCHECK(data_ptr);
296 #endif
177 memset(data_ptr, 0, capture_buffer->size()); 297 memset(data_ptr, 0, capture_buffer->size());
178 298
179 DrawPacman( 299 DrawPacman(
180 (pixel_format == media::PIXEL_FORMAT_GPUMEMORYBUFFER), /* use_argb */ 300 (pixel_format == media::PIXEL_FORMAT_GPUMEMORYBUFFER), /* use_argb */
181 data_ptr, 301 data_ptr,
182 frame_count_, 302 frame_count_,
183 kFakeCapturePeriodMs, 303 kFakeCapturePeriodMs,
184 capture_format_.frame_size); 304 capture_format_.frame_size);
185 305
186 // Give the captured frame to the client. 306 // Give the captured frame to the client.
(...skipping 14 matching lines...) Expand all
201 // Generate a synchronized beep sound every so many frames. 321 // Generate a synchronized beep sound every so many frames.
202 if (frame_count_++ % kFakeCaptureBeepCycle == 0) 322 if (frame_count_++ % kFakeCaptureBeepCycle == 0)
203 FakeAudioInputStream::BeepOnce(); 323 FakeAudioInputStream::BeepOnce();
204 324
205 // Reschedule next CaptureTask. 325 // Reschedule next CaptureTask.
206 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, next_capture, 326 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, next_capture,
207 base::TimeDelta::FromMilliseconds(kFakeCapturePeriodMs)); 327 base::TimeDelta::FromMilliseconds(kFakeCapturePeriodMs));
208 } 328 }
209 329
210 } // namespace media 330 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698