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" |
11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
12 #include "media/audio/fake_audio_input_stream.h" | 12 #include "media/audio/fake_audio_input_stream.h" |
13 #include "media/base/encoded_bitstream_buffer.h" | |
13 #include "third_party/skia/include/core/SkBitmap.h" | 14 #include "third_party/skia/include/core/SkBitmap.h" |
14 #include "third_party/skia/include/core/SkCanvas.h" | 15 #include "third_party/skia/include/core/SkCanvas.h" |
15 #include "third_party/skia/include/core/SkPaint.h" | 16 #include "third_party/skia/include/core/SkPaint.h" |
16 | 17 |
17 namespace media { | 18 namespace media { |
18 | 19 |
19 static const int kFakeCaptureTimeoutMs = 50; | 20 namespace { |
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
not adding value
sheu
2013/08/22 22:40:31
Fine :-P
| |
20 static const int kFakeCaptureBeepCycle = 20; // Visual beep every 1s. | 21 |
22 const int kFakeCaptureTimeoutMs = 50; | |
23 const int kFakeCaptureBeepCycle = 20; // Visual beep every 1s. | |
21 enum { kNumberOfFakeDevices = 2 }; | 24 enum { kNumberOfFakeDevices = 2 }; |
22 | 25 |
26 } // anonymous namespace | |
27 | |
23 bool FakeVideoCaptureDevice::fail_next_create_ = false; | 28 bool FakeVideoCaptureDevice::fail_next_create_ = false; |
24 | 29 |
25 void FakeVideoCaptureDevice::GetDeviceNames(Names* const device_names) { | 30 void FakeVideoCaptureDevice::GetDeviceNames(Names* const device_names, |
31 bool encoded_capture) { | |
26 // Empty the name list. | 32 // Empty the name list. |
27 device_names->erase(device_names->begin(), device_names->end()); | 33 device_names->erase(device_names->begin(), device_names->end()); |
28 | 34 |
29 for (int n = 0; n < kNumberOfFakeDevices; n++) { | 35 for (int n = 0; n < kNumberOfFakeDevices; n++) { |
30 Name name; | 36 Name name; |
31 name.unique_id = base::StringPrintf("/dev/video%d", n); | 37 name.unique_id = base::StringPrintf("/dev/video%d", n); |
32 name.device_name = base::StringPrintf("fake_device_%d", n); | 38 name.device_name = base::StringPrintf( |
39 "fake_%sdevice_%d", | |
40 (encoded_capture ? "encoded_" : ""), | |
41 n); | |
33 device_names->push_back(name); | 42 device_names->push_back(name); |
34 } | 43 } |
35 } | 44 } |
36 | 45 |
37 VideoCaptureDevice* FakeVideoCaptureDevice::Create(const Name& device_name) { | 46 VideoCaptureDevice* FakeVideoCaptureDevice::Create(const Name& device_name, |
47 bool encoded_capture) { | |
38 if (fail_next_create_) { | 48 if (fail_next_create_) { |
39 fail_next_create_ = false; | 49 fail_next_create_ = false; |
40 return NULL; | 50 return NULL; |
41 } | 51 } |
42 for (int n = 0; n < kNumberOfFakeDevices; ++n) { | 52 for (int n = 0; n < kNumberOfFakeDevices; ++n) { |
43 std::string possible_id = base::StringPrintf("/dev/video%d", n); | 53 std::string possible_id = base::StringPrintf("/dev/video%d", n); |
44 if (device_name.unique_id.compare(possible_id) == 0) { | 54 if (device_name.unique_id.compare(possible_id) == 0) { |
45 return new FakeVideoCaptureDevice(device_name); | 55 return new FakeVideoCaptureDevice(device_name, encoded_capture); |
46 } | 56 } |
47 } | 57 } |
48 return NULL; | 58 return NULL; |
49 } | 59 } |
50 | 60 |
51 void FakeVideoCaptureDevice::SetFailNextCreate() { | 61 void FakeVideoCaptureDevice::SetFailNextCreate() { |
52 fail_next_create_ = true; | 62 fail_next_create_ = true; |
53 } | 63 } |
54 | 64 |
55 FakeVideoCaptureDevice::FakeVideoCaptureDevice(const Name& device_name) | 65 FakeVideoCaptureDevice::FakeVideoCaptureDevice(const Name& device_name, |
66 bool encoded_capture) | |
56 : device_name_(device_name), | 67 : device_name_(device_name), |
68 encoded_capture_(encoded_capture), | |
57 observer_(NULL), | 69 observer_(NULL), |
58 state_(kIdle), | 70 state_(kIdle), |
59 capture_thread_("CaptureThread"), | 71 capture_thread_("CaptureThread"), |
60 frame_size_(0), | 72 frame_size_(0), |
61 frame_count_(0), | 73 frame_count_(0), |
62 frame_width_(0), | 74 frame_width_(0), |
63 frame_height_(0) { | 75 frame_height_(0) { |
64 } | 76 } |
65 | 77 |
66 FakeVideoCaptureDevice::~FakeVideoCaptureDevice() { | 78 FakeVideoCaptureDevice::~FakeVideoCaptureDevice() { |
67 // Check if the thread is running. | 79 // Check if the thread is running. |
68 // This means that the device have not been DeAllocated properly. | 80 // This means that the device have not been DeAllocated properly. |
69 DCHECK(!capture_thread_.IsRunning()); | 81 DCHECK(!capture_thread_.IsRunning()); |
70 } | 82 } |
71 | 83 |
84 VideoEncodingCapabilities FakeVideoCaptureDevice::GetEncodingCapabilities() { | |
85 media::VideoEncodingCapabilities capabilities; | |
86 if (encoded_capture_) { | |
87 media::VideoEncodingConfig config; | |
88 config.codec_type = kCodecVP8; | |
89 config.codec_name = "VP8"; | |
90 config.max_resolution.SetSize(640, 480); | |
91 config.max_frames_per_second = 30; | |
92 config.max_bitrate = 1024 * 1024; | |
93 capabilities.push_back(config); | |
94 } | |
95 return capabilities; | |
96 } | |
97 | |
98 void FakeVideoCaptureDevice::TryConfigureEncodedBitstream( | |
99 const RuntimeVideoEncodingParameters& params) { | |
100 DCHECK(encoded_capture_); | |
101 DCHECK(observer_); | |
102 observer_->OnBitstreamConfigChanged(params); | |
103 } | |
104 | |
72 void FakeVideoCaptureDevice::Allocate(int width, | 105 void FakeVideoCaptureDevice::Allocate(int width, |
73 int height, | 106 int height, |
74 int frame_rate, | 107 int frame_rate, |
75 EventHandler* observer) { | 108 EventHandler* observer) { |
76 if (state_ != kIdle) { | 109 if (state_ != kIdle) { |
77 return; // Wrong state. | 110 return; // Wrong state. |
78 } | 111 } |
79 | 112 |
113 DCHECK(!observer_); | |
80 observer_ = observer; | 114 observer_ = observer; |
81 VideoCaptureCapability current_settings; | 115 state_ = kAllocated; |
82 current_settings.color = VideoCaptureCapability::kI420; | 116 |
83 current_settings.expected_capture_delay = 0; | 117 if (encoded_capture_) { |
84 current_settings.interlaced = false; | 118 media::VideoEncodingParameters params; |
85 if (width > 320) { // VGA | 119 params.codec_name = std::string("VP8"); |
86 current_settings.width = 640; | 120 params.resolution.SetSize(640, 480); |
87 current_settings.height = 480; | 121 params.runtime_params.target_bitrate = 512; |
88 current_settings.frame_rate = 30; | 122 params.runtime_params.max_bitrate = 1024; |
89 } else { // QVGA | 123 params.runtime_params.frames_per_second = 30; |
90 current_settings.width = 320; | 124 observer_->OnEncodedFrameInfo(params); |
91 current_settings.height = 240; | 125 } else { |
92 current_settings.frame_rate = 30; | 126 VideoCaptureCapability current_settings; |
127 current_settings.color = VideoCaptureCapability::kI420; | |
128 current_settings.expected_capture_delay = 0; | |
129 current_settings.interlaced = false; | |
130 if (width > 320) { // VGA | |
131 current_settings.width = 640; | |
132 current_settings.height = 480; | |
133 current_settings.frame_rate = 30; | |
134 } else { // QVGA | |
135 current_settings.width = 320; | |
136 current_settings.height = 240; | |
137 current_settings.frame_rate = 30; | |
138 } | |
139 | |
140 size_t fake_frame_size = | |
141 current_settings.width * current_settings.height * 3 / 2; | |
142 fake_frame_.reset(new uint8[fake_frame_size]); | |
143 memset(fake_frame_.get(), 0, fake_frame_size); | |
144 frame_size_ = fake_frame_size; | |
145 frame_width_ = current_settings.width; | |
146 frame_height_ = current_settings.height; | |
147 observer_->OnFrameInfo(current_settings); | |
93 } | 148 } |
94 | |
95 size_t fake_frame_size = | |
96 current_settings.width * current_settings.height * 3 / 2; | |
97 fake_frame_.reset(new uint8[fake_frame_size]); | |
98 memset(fake_frame_.get(), 0, fake_frame_size); | |
99 frame_size_ = fake_frame_size; | |
100 frame_width_ = current_settings.width; | |
101 frame_height_ = current_settings.height; | |
102 | |
103 state_ = kAllocated; | |
104 observer_->OnFrameInfo(current_settings); | |
105 } | 149 } |
106 | 150 |
107 void FakeVideoCaptureDevice::Start() { | 151 void FakeVideoCaptureDevice::Start() { |
108 if (state_ != kAllocated) { | 152 if (state_ != kAllocated) { |
109 return; // Wrong state. | 153 return; // Wrong state. |
110 } | 154 } |
111 state_ = kCapturing; | 155 state_ = kCapturing; |
112 capture_thread_.Start(); | 156 capture_thread_.Start(); |
113 capture_thread_.message_loop()->PostTask( | 157 capture_thread_.message_loop()->PostTask( |
114 FROM_HERE, | 158 FROM_HERE, |
115 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask, | 159 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask, |
116 base::Unretained(this))); | 160 base::Unretained(this))); |
117 } | 161 } |
118 | 162 |
119 void FakeVideoCaptureDevice::Stop() { | 163 void FakeVideoCaptureDevice::Stop() { |
120 if (state_ != kCapturing) { | 164 if (state_ != kCapturing) { |
121 return; // Wrong state. | 165 return; // Wrong state. |
122 } | 166 } |
123 capture_thread_.Stop(); | 167 capture_thread_.Stop(); |
124 state_ = kAllocated; | 168 state_ = kAllocated; |
125 } | 169 } |
126 | 170 |
127 void FakeVideoCaptureDevice::DeAllocate() { | 171 void FakeVideoCaptureDevice::DeAllocate() { |
128 if (state_ != kAllocated && state_ != kCapturing) { | 172 if (state_ != kAllocated && state_ != kCapturing) { |
129 return; // Wrong state. | 173 return; // Wrong state. |
130 } | 174 } |
131 capture_thread_.Stop(); | 175 capture_thread_.Stop(); |
132 state_ = kIdle; | 176 state_ = kIdle; |
177 observer_ = NULL; | |
133 } | 178 } |
134 | 179 |
135 const VideoCaptureDevice::Name& FakeVideoCaptureDevice::device_name() { | 180 const VideoCaptureDevice::Name& FakeVideoCaptureDevice::device_name() { |
136 return device_name_; | 181 return device_name_; |
137 } | 182 } |
138 | 183 |
139 void FakeVideoCaptureDevice::OnCaptureTask() { | 184 void FakeVideoCaptureDevice::OnCaptureTask() { |
140 if (state_ != kCapturing) { | 185 if (state_ != kCapturing) { |
141 return; | 186 return; |
142 } | 187 } |
143 | 188 |
144 memset(fake_frame_.get(), 0, frame_size_); | 189 memset(fake_frame_.get(), 0, frame_size_); |
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
only used in the not-encoding case
sheu
2013/08/22 22:40:31
Also used for encoding. Changed up a bit here.
| |
145 | 190 |
146 SkBitmap bitmap; | 191 if (encoded_capture_) { |
147 bitmap.setConfig(SkBitmap::kA8_Config, frame_width_, frame_height_, | 192 // Just return empty frames. |
148 frame_width_); | 193 scoped_refptr<media::EncodedBitstreamBuffer> buffer = |
149 bitmap.setPixels(fake_frame_.get()); | 194 observer_->ReserveOutputEncodedBitstreamBuffer(); |
195 if (buffer) { | |
196 observer_->OnIncomingCapturedEncodedBitstreamBuffer( | |
197 buffer, | |
198 0, | |
199 base::Time::Now()); | |
200 } | |
201 } else { | |
202 SkBitmap bitmap; | |
203 bitmap.setConfig(SkBitmap::kA8_Config, frame_width_, frame_height_, | |
204 frame_width_); | |
205 bitmap.setPixels(fake_frame_.get()); | |
150 | 206 |
151 SkCanvas canvas(bitmap); | 207 SkCanvas canvas(bitmap); |
152 | 208 |
153 // Draw a sweeping circle to show an animation. | 209 // Draw a sweeping circle to show an animation. |
154 int radius = std::min(frame_width_, frame_height_) / 4; | 210 int radius = std::min(frame_width_, frame_height_) / 4; |
155 SkRect rect = SkRect::MakeXYWH( | 211 SkRect rect = SkRect::MakeXYWH( |
156 frame_width_ / 2 - radius, frame_height_ / 2 - radius, | 212 frame_width_ / 2 - radius, frame_height_ / 2 - radius, |
157 2 * radius, 2 * radius); | 213 2 * radius, 2 * radius); |
158 | 214 |
159 SkPaint paint; | 215 SkPaint paint; |
160 paint.setStyle(SkPaint::kFill_Style); | 216 paint.setStyle(SkPaint::kFill_Style); |
161 | 217 |
162 // Only Y plane is being drawn and this gives 50% grey on the Y | 218 // Only Y plane is being drawn and this gives 50% grey on the Y |
163 // plane. The result is a light green color in RGB space. | 219 // plane. The result is a light green color in RGB space. |
164 paint.setAlpha(128); | 220 paint.setAlpha(128); |
165 | 221 |
166 int end_angle = (frame_count_ % kFakeCaptureBeepCycle * 360) / | 222 int end_angle = (frame_count_ % kFakeCaptureBeepCycle * 360) / |
167 kFakeCaptureBeepCycle; | 223 kFakeCaptureBeepCycle; |
168 if (!end_angle) | 224 if (!end_angle) |
169 end_angle = 360; | 225 end_angle = 360; |
170 canvas.drawArc(rect, 0, end_angle, true, paint); | 226 canvas.drawArc(rect, 0, end_angle, true, paint); |
171 | 227 |
172 // Draw current time. | 228 // Draw current time. |
173 int elapsed_ms = kFakeCaptureTimeoutMs * frame_count_; | 229 int elapsed_ms = kFakeCaptureTimeoutMs * frame_count_; |
174 int milliseconds = elapsed_ms % 1000; | 230 int milliseconds = elapsed_ms % 1000; |
175 int seconds = (elapsed_ms / 1000) % 60; | 231 int seconds = (elapsed_ms / 1000) % 60; |
176 int minutes = (elapsed_ms / 1000 / 60) % 60; | 232 int minutes = (elapsed_ms / 1000 / 60) % 60; |
177 int hours = (elapsed_ms / 1000 / 60 / 60) % 60; | 233 int hours = (elapsed_ms / 1000 / 60 / 60) % 60; |
178 | 234 |
179 std::string time_string = | 235 std::string time_string = |
180 base::StringPrintf("%d:%02d:%02d:%03d %d", hours, minutes, | 236 base::StringPrintf("%d:%02d:%02d:%03d %d", hours, minutes, |
181 seconds, milliseconds, frame_count_); | 237 seconds, milliseconds, frame_count_); |
182 canvas.scale(3, 3); | 238 canvas.scale(3, 3); |
183 canvas.drawText(time_string.data(), time_string.length(), 30, 20, | 239 canvas.drawText(time_string.data(), time_string.length(), 30, 20, |
184 paint); | 240 paint); |
185 | 241 |
186 if (frame_count_ % kFakeCaptureBeepCycle == 0) { | 242 if (frame_count_ % kFakeCaptureBeepCycle == 0) { |
187 // Generate a synchronized beep sound if there is one audio input | 243 // Generate a synchronized beep sound if there is one audio input |
188 // stream created. | 244 // stream created. |
189 FakeAudioInputStream::BeepOnce(); | 245 FakeAudioInputStream::BeepOnce(); |
190 } | 246 } |
191 | 247 |
192 frame_count_++; | 248 frame_count_++; |
193 | 249 |
194 // Give the captured frame to the observer. | 250 // Give the captured frame to the observer. |
195 observer_->OnIncomingCapturedFrame( | 251 observer_->OnIncomingCapturedFrame( |
196 fake_frame_.get(), frame_size_, base::Time::Now(), 0, false, false); | 252 fake_frame_.get(), frame_size_, base::Time::Now(), 0, false, false); |
253 } | |
254 | |
197 // Reschedule next CaptureTask. | 255 // Reschedule next CaptureTask. |
198 capture_thread_.message_loop()->PostDelayedTask( | 256 capture_thread_.message_loop()->PostDelayedTask( |
199 FROM_HERE, | 257 FROM_HERE, |
200 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask, | 258 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask, |
201 base::Unretained(this)), | 259 base::Unretained(this)), |
202 base::TimeDelta::FromMilliseconds(kFakeCaptureTimeoutMs)); | 260 base::TimeDelta::FromMilliseconds(kFakeCaptureTimeoutMs)); |
203 } | 261 } |
204 | 262 |
205 } // namespace media | 263 } // namespace media |
OLD | NEW |