| 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 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 for (int n = 0; n < kNumberOfFakeDevices; n++) { | 30 for (int n = 0; n < kNumberOfFakeDevices; n++) { |
| 31 Name name(base::StringPrintf("fake_device_%d", n), | 31 Name name(base::StringPrintf("fake_device_%d", n), |
| 32 base::StringPrintf("/dev/video%d", n)); | 32 base::StringPrintf("/dev/video%d", n)); |
| 33 device_names->push_back(name); | 33 device_names->push_back(name); |
| 34 } | 34 } |
| 35 } | 35 } |
| 36 | 36 |
| 37 void FakeVideoCaptureDevice::GetDeviceSupportedFormats( | 37 void FakeVideoCaptureDevice::GetDeviceSupportedFormats( |
| 38 const Name& device, | 38 const Name& device, |
| 39 VideoCaptureCapabilities* formats) { | 39 VideoCaptureCapabilities* formats) { |
| 40 VideoCaptureCapability capture_format_640x480; | 40 VideoCaptureCapability capture_format; |
| 41 capture_format_640x480.supported_format.frame_size.SetSize(640, 480); | 41 capture_format.color = media::PIXEL_FORMAT_I420; |
| 42 capture_format_640x480.supported_format.frame_rate = | 42 capture_format.width = 640; |
| 43 1000 / kFakeCaptureTimeoutMs; | 43 capture_format.height = 480; |
| 44 capture_format_640x480.supported_format.pixel_format = | 44 capture_format.frame_rate = 1000 / kFakeCaptureTimeoutMs; |
| 45 media::PIXEL_FORMAT_I420; | 45 formats->push_back(capture_format); |
| 46 formats->push_back(capture_format_640x480); | |
| 47 } | 46 } |
| 48 | 47 |
| 49 VideoCaptureDevice* FakeVideoCaptureDevice::Create(const Name& device_name) { | 48 VideoCaptureDevice* FakeVideoCaptureDevice::Create(const Name& device_name) { |
| 50 if (fail_next_create_) { | 49 if (fail_next_create_) { |
| 51 fail_next_create_ = false; | 50 fail_next_create_ = false; |
| 52 return NULL; | 51 return NULL; |
| 53 } | 52 } |
| 54 for (int n = 0; n < kNumberOfFakeDevices; ++n) { | 53 for (int n = 0; n < kNumberOfFakeDevices; ++n) { |
| 55 std::string possible_id = base::StringPrintf("/dev/video%d", n); | 54 std::string possible_id = base::StringPrintf("/dev/video%d", n); |
| 56 if (device_name.id().compare(possible_id) == 0) { | 55 if (device_name.id().compare(possible_id) == 0) { |
| 57 return new FakeVideoCaptureDevice(); | 56 return new FakeVideoCaptureDevice(); |
| 58 } | 57 } |
| 59 } | 58 } |
| 60 return NULL; | 59 return NULL; |
| 61 } | 60 } |
| 62 | 61 |
| 63 void FakeVideoCaptureDevice::SetFailNextCreate() { | 62 void FakeVideoCaptureDevice::SetFailNextCreate() { |
| 64 fail_next_create_ = true; | 63 fail_next_create_ = true; |
| 65 } | 64 } |
| 66 | 65 |
| 67 FakeVideoCaptureDevice::FakeVideoCaptureDevice() | 66 FakeVideoCaptureDevice::FakeVideoCaptureDevice() |
| 68 : state_(kIdle), | 67 : state_(kIdle), |
| 69 capture_thread_("CaptureThread"), | 68 capture_thread_("CaptureThread"), |
| 70 frame_count_(0), | 69 frame_count_(0), |
| 71 format_roster_index_(0) {} | 70 capabilities_roster_index_(0) { |
| 71 } |
| 72 | 72 |
| 73 FakeVideoCaptureDevice::~FakeVideoCaptureDevice() { | 73 FakeVideoCaptureDevice::~FakeVideoCaptureDevice() { |
| 74 // Check if the thread is running. | 74 // Check if the thread is running. |
| 75 // This means that the device have not been DeAllocated properly. | 75 // This means that the device have not been DeAllocated properly. |
| 76 DCHECK(!capture_thread_.IsRunning()); | 76 DCHECK(!capture_thread_.IsRunning()); |
| 77 } | 77 } |
| 78 | 78 |
| 79 void FakeVideoCaptureDevice::AllocateAndStart( | 79 void FakeVideoCaptureDevice::AllocateAndStart( |
| 80 const VideoCaptureParams& params, | 80 const VideoCaptureCapability& capture_format, |
| 81 scoped_ptr<VideoCaptureDevice::Client> client) { | 81 scoped_ptr<VideoCaptureDevice::Client> client) { |
| 82 if (params.allow_resolution_change) | 82 capture_format_.frame_size_type = capture_format.frame_size_type; |
| 83 PopulateFormatRoster(); | 83 if (capture_format.frame_size_type == VariableResolutionVideoCaptureDevice) |
| 84 PopulateCapabilitiesRoster(); |
| 84 | 85 |
| 85 if (state_ != kIdle) { | 86 if (state_ != kIdle) { |
| 86 return; // Wrong state. | 87 return; // Wrong state. |
| 87 } | 88 } |
| 88 | 89 |
| 89 client_ = client.Pass(); | 90 client_ = client.Pass(); |
| 90 capture_format_.pixel_format = PIXEL_FORMAT_I420; | 91 capture_format_.color = PIXEL_FORMAT_I420; |
| 91 if (params.requested_format.frame_size.width() > 320) { // VGA | 92 if (capture_format.width > 320) { // VGA |
| 92 capture_format_.frame_size.SetSize(640, 480); | 93 capture_format_.width = 640; |
| 94 capture_format_.height = 480; |
| 93 capture_format_.frame_rate = 30; | 95 capture_format_.frame_rate = 30; |
| 94 } else { // QVGA | 96 } else { // QVGA |
| 95 capture_format_.frame_size.SetSize(320, 240); | 97 capture_format_.width = 320; |
| 98 capture_format_.height = 240; |
| 96 capture_format_.frame_rate = 30; | 99 capture_format_.frame_rate = 30; |
| 97 } | 100 } |
| 98 | 101 |
| 99 const size_t fake_frame_size = | 102 const size_t fake_frame_size = VideoFrame::AllocationSize( |
| 100 VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size); | 103 VideoFrame::I420, |
| 104 gfx::Size(capture_format_.width, capture_format_.height)); |
| 101 fake_frame_.reset(new uint8[fake_frame_size]); | 105 fake_frame_.reset(new uint8[fake_frame_size]); |
| 102 | 106 |
| 103 state_ = kCapturing; | 107 state_ = kCapturing; |
| 104 capture_thread_.Start(); | 108 capture_thread_.Start(); |
| 105 capture_thread_.message_loop()->PostTask( | 109 capture_thread_.message_loop()->PostTask( |
| 106 FROM_HERE, | 110 FROM_HERE, |
| 107 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask, | 111 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask, |
| 108 base::Unretained(this))); | 112 base::Unretained(this))); |
| 109 } | 113 } |
| 110 | 114 |
| 111 void FakeVideoCaptureDevice::Reallocate() { | 115 void FakeVideoCaptureDevice::Reallocate() { |
| 112 DCHECK_EQ(state_, kCapturing); | 116 DCHECK_EQ(state_, kCapturing); |
| 113 capture_format_ = | 117 capture_format_ = capabilities_roster_.at(++capabilities_roster_index_ % |
| 114 format_roster_.at(++format_roster_index_ % format_roster_.size()); | 118 capabilities_roster_.size()); |
| 115 DCHECK_EQ(capture_format_.pixel_format, PIXEL_FORMAT_I420); | 119 DCHECK_EQ(capture_format_.color, PIXEL_FORMAT_I420); |
| 116 DVLOG(3) << "Reallocating FakeVideoCaptureDevice, new capture resolution " | 120 DVLOG(3) << "Reallocating FakeVideoCaptureDevice, new capture resolution (" |
| 117 << capture_format_.frame_size.ToString(); | 121 << capture_format_.width << "x" << capture_format_.height << ")"; |
| 118 | 122 |
| 119 const size_t fake_frame_size = | 123 const size_t fake_frame_size = VideoFrame::AllocationSize( |
| 120 VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size); | 124 VideoFrame::I420, |
| 125 gfx::Size(capture_format_.width, capture_format_.height)); |
| 121 fake_frame_.reset(new uint8[fake_frame_size]); | 126 fake_frame_.reset(new uint8[fake_frame_size]); |
| 122 } | 127 } |
| 123 | 128 |
| 124 void FakeVideoCaptureDevice::StopAndDeAllocate() { | 129 void FakeVideoCaptureDevice::StopAndDeAllocate() { |
| 125 if (state_ != kCapturing) { | 130 if (state_ != kCapturing) { |
| 126 return; // Wrong state. | 131 return; // Wrong state. |
| 127 } | 132 } |
| 128 capture_thread_.Stop(); | 133 capture_thread_.Stop(); |
| 129 state_ = kIdle; | 134 state_ = kIdle; |
| 130 } | 135 } |
| 131 | 136 |
| 132 void FakeVideoCaptureDevice::OnCaptureTask() { | 137 void FakeVideoCaptureDevice::OnCaptureTask() { |
| 133 if (state_ != kCapturing) { | 138 if (state_ != kCapturing) { |
| 134 return; | 139 return; |
| 135 } | 140 } |
| 136 | 141 |
| 137 const size_t frame_size = | 142 const size_t frame_size = VideoFrame::AllocationSize( |
| 138 VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size); | 143 VideoFrame::I420, |
| 144 gfx::Size(capture_format_.width, capture_format_.height)); |
| 139 memset(fake_frame_.get(), 0, frame_size); | 145 memset(fake_frame_.get(), 0, frame_size); |
| 140 | 146 |
| 141 SkBitmap bitmap; | 147 SkBitmap bitmap; |
| 142 bitmap.setConfig(SkBitmap::kA8_Config, | 148 bitmap.setConfig(SkBitmap::kA8_Config, |
| 143 capture_format_.frame_size.width(), | 149 capture_format_.width, |
| 144 capture_format_.frame_size.height(), | 150 capture_format_.height, |
| 145 capture_format_.frame_size.width()), | 151 capture_format_.width); |
| 146 bitmap.setPixels(fake_frame_.get()); | 152 bitmap.setPixels(fake_frame_.get()); |
| 147 | 153 |
| 148 SkCanvas canvas(bitmap); | 154 SkCanvas canvas(bitmap); |
| 149 | 155 |
| 150 // Draw a sweeping circle to show an animation. | 156 // Draw a sweeping circle to show an animation. |
| 151 int radius = std::min(capture_format_.frame_size.width(), | 157 int radius = std::min(capture_format_.width, capture_format_.height) / 4; |
| 152 capture_format_.frame_size.height()) / | 158 SkRect rect = SkRect::MakeXYWH( |
| 153 4; | 159 capture_format_.width / 2 - radius, capture_format_.height / 2 - radius, |
| 154 SkRect rect = | 160 2 * radius, 2 * radius); |
| 155 SkRect::MakeXYWH(capture_format_.frame_size.width() / 2 - radius, | |
| 156 capture_format_.frame_size.height() / 2 - radius, | |
| 157 2 * radius, | |
| 158 2 * radius); | |
| 159 | 161 |
| 160 SkPaint paint; | 162 SkPaint paint; |
| 161 paint.setStyle(SkPaint::kFill_Style); | 163 paint.setStyle(SkPaint::kFill_Style); |
| 162 | 164 |
| 163 // Only Y plane is being drawn and this gives 50% grey on the Y | 165 // Only Y plane is being drawn and this gives 50% grey on the Y |
| 164 // plane. The result is a light green color in RGB space. | 166 // plane. The result is a light green color in RGB space. |
| 165 paint.setAlpha(128); | 167 paint.setAlpha(128); |
| 166 | 168 |
| 167 int end_angle = (frame_count_ % kFakeCaptureBeepCycle * 360) / | 169 int end_angle = (frame_count_ % kFakeCaptureBeepCycle * 360) / |
| 168 kFakeCaptureBeepCycle; | 170 kFakeCaptureBeepCycle; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 194 | 196 |
| 195 // Give the captured frame to the client. | 197 // Give the captured frame to the client. |
| 196 client_->OnIncomingCapturedFrame(fake_frame_.get(), | 198 client_->OnIncomingCapturedFrame(fake_frame_.get(), |
| 197 frame_size, | 199 frame_size, |
| 198 base::Time::Now(), | 200 base::Time::Now(), |
| 199 0, | 201 0, |
| 200 false, | 202 false, |
| 201 false, | 203 false, |
| 202 capture_format_); | 204 capture_format_); |
| 203 if (!(frame_count_ % kFakeCaptureCapabilityChangePeriod) && | 205 if (!(frame_count_ % kFakeCaptureCapabilityChangePeriod) && |
| 204 format_roster_.size() > 0U) { | 206 (capture_format_.frame_size_type == |
| 207 VariableResolutionVideoCaptureDevice)) { |
| 205 Reallocate(); | 208 Reallocate(); |
| 206 } | 209 } |
| 207 // Reschedule next CaptureTask. | 210 // Reschedule next CaptureTask. |
| 208 capture_thread_.message_loop()->PostDelayedTask( | 211 capture_thread_.message_loop()->PostDelayedTask( |
| 209 FROM_HERE, | 212 FROM_HERE, |
| 210 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask, | 213 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask, |
| 211 base::Unretained(this)), | 214 base::Unretained(this)), |
| 212 base::TimeDelta::FromMilliseconds(kFakeCaptureTimeoutMs)); | 215 base::TimeDelta::FromMilliseconds(kFakeCaptureTimeoutMs)); |
| 213 } | 216 } |
| 214 | 217 |
| 215 void FakeVideoCaptureDevice::PopulateFormatRoster() { | 218 void FakeVideoCaptureDevice::PopulateCapabilitiesRoster() { |
| 216 format_roster_.push_back( | 219 capabilities_roster_.push_back( |
| 217 media::VideoCaptureFormat(gfx::Size(320, 240), 30, PIXEL_FORMAT_I420)); | 220 media::VideoCaptureCapability(320, |
| 218 format_roster_.push_back( | 221 240, |
| 219 media::VideoCaptureFormat(gfx::Size(640, 480), 30, PIXEL_FORMAT_I420)); | 222 30, |
| 220 format_roster_.push_back( | 223 PIXEL_FORMAT_I420, |
| 221 media::VideoCaptureFormat(gfx::Size(800, 600), 30, PIXEL_FORMAT_I420)); | 224 VariableResolutionVideoCaptureDevice)); |
| 225 capabilities_roster_.push_back( |
| 226 media::VideoCaptureCapability(640, |
| 227 480, |
| 228 30, |
| 229 PIXEL_FORMAT_I420, |
| 230 VariableResolutionVideoCaptureDevice)); |
| 231 capabilities_roster_.push_back( |
| 232 media::VideoCaptureCapability(800, |
| 233 600, |
| 234 30, |
| 235 PIXEL_FORMAT_I420, |
| 236 VariableResolutionVideoCaptureDevice)); |
| 222 | 237 |
| 223 format_roster_index_ = 0; | 238 capabilities_roster_index_ = 0; |
| 224 } | 239 } |
| 225 | 240 |
| 226 } // namespace media | 241 } // namespace media |
| OLD | NEW |