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

Side by Side Diff: media/video/capture/fake_video_capture_device.cc

Issue 15906019: Hook up EncodedVideoSource on the browser side (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@screencast_cl_6
Patch Set: 516738a8 IPC/struct changes, courtesy hshi@ Created 7 years, 6 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 #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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698