Chromium Code Reviews| 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 |