OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |