Disable firewall check. It takes signifficant time, need to be on FILE thread.
[chromium-blink-merge.git] / media / video / capture / fake_video_capture_device.cc
blob302396a22b8bd77a1c67cbd2d983d01a5564fb6f
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
3 // found in the LICENSE file.
5 #include "media/video/capture/fake_video_capture_device.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/stringprintf.h"
12 #include "media/audio/fake_audio_input_stream.h"
13 #include "media/base/video_frame.h"
14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkPaint.h"
18 namespace media {
20 static const int kFakeCaptureBeepCycle = 10; // Visual beep every 0.5s.
21 static const int kFakeCaptureCapabilityChangePeriod = 30;
23 FakeVideoCaptureDevice::FakeVideoCaptureDevice()
24 : capture_thread_("CaptureThread"),
25 frame_count_(0),
26 format_roster_index_(0) {}
28 FakeVideoCaptureDevice::~FakeVideoCaptureDevice() {
29 DCHECK(thread_checker_.CalledOnValidThread());
30 DCHECK(!capture_thread_.IsRunning());
33 void FakeVideoCaptureDevice::AllocateAndStart(
34 const VideoCaptureParams& params,
35 scoped_ptr<VideoCaptureDevice::Client> client) {
36 DCHECK(thread_checker_.CalledOnValidThread());
37 DCHECK(!capture_thread_.IsRunning());
39 capture_thread_.Start();
40 capture_thread_.message_loop()->PostTask(
41 FROM_HERE,
42 base::Bind(&FakeVideoCaptureDevice::OnAllocateAndStart,
43 base::Unretained(this),
44 params,
45 base::Passed(&client)));
48 void FakeVideoCaptureDevice::StopAndDeAllocate() {
49 DCHECK(thread_checker_.CalledOnValidThread());
50 DCHECK(capture_thread_.IsRunning());
51 capture_thread_.message_loop()->PostTask(
52 FROM_HERE,
53 base::Bind(&FakeVideoCaptureDevice::OnStopAndDeAllocate,
54 base::Unretained(this)));
55 capture_thread_.Stop();
58 void FakeVideoCaptureDevice::PopulateVariableFormatsRoster(
59 const VideoCaptureFormats& formats) {
60 DCHECK(thread_checker_.CalledOnValidThread());
61 DCHECK(!capture_thread_.IsRunning());
62 format_roster_ = formats;
63 format_roster_index_ = 0;
66 void FakeVideoCaptureDevice::OnAllocateAndStart(
67 const VideoCaptureParams& params,
68 scoped_ptr<VideoCaptureDevice::Client> client) {
69 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current());
70 client_ = client.Pass();
72 // Incoming |params| can be none of the supported formats, so we get the
73 // closest thing rounded up. TODO(mcasas): Use the |params|, if they belong to
74 // the supported ones, when http://crbug.com/309554 is verified.
75 DCHECK_EQ(params.requested_format.pixel_format, PIXEL_FORMAT_I420);
76 capture_format_.pixel_format = params.requested_format.pixel_format;
77 capture_format_.frame_rate = 30;
78 if (params.requested_format.frame_size.width() > 640)
79 capture_format_.frame_size.SetSize(1280, 720);
80 else if (params.requested_format.frame_size.width() > 320)
81 capture_format_.frame_size.SetSize(640, 480);
82 else
83 capture_format_.frame_size.SetSize(320, 240);
84 const size_t fake_frame_size =
85 VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size);
86 fake_frame_.reset(new uint8[fake_frame_size]);
88 capture_thread_.message_loop()->PostTask(
89 FROM_HERE,
90 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask,
91 base::Unretained(this)));
94 void FakeVideoCaptureDevice::OnStopAndDeAllocate() {
95 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current());
96 client_.reset();
99 void FakeVideoCaptureDevice::OnCaptureTask() {
100 if (!client_)
101 return;
103 const size_t frame_size =
104 VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size);
105 memset(fake_frame_.get(), 0, frame_size);
107 SkBitmap bitmap;
108 bitmap.setConfig(SkBitmap::kA8_Config,
109 capture_format_.frame_size.width(),
110 capture_format_.frame_size.height(),
111 capture_format_.frame_size.width()),
112 bitmap.setPixels(fake_frame_.get());
113 SkCanvas canvas(bitmap);
115 // Draw a sweeping circle to show an animation.
116 int radius = std::min(capture_format_.frame_size.width(),
117 capture_format_.frame_size.height()) / 4;
118 SkRect rect =
119 SkRect::MakeXYWH(capture_format_.frame_size.width() / 2 - radius,
120 capture_format_.frame_size.height() / 2 - radius,
121 2 * radius,
122 2 * radius);
124 SkPaint paint;
125 paint.setStyle(SkPaint::kFill_Style);
127 // Only Y plane is being drawn and this gives 50% grey on the Y
128 // plane. The result is a light green color in RGB space.
129 paint.setAlpha(128);
131 int end_angle = (frame_count_ % kFakeCaptureBeepCycle * 360) /
132 kFakeCaptureBeepCycle;
133 if (!end_angle)
134 end_angle = 360;
135 canvas.drawArc(rect, 0, end_angle, true, paint);
137 // Draw current time.
138 int elapsed_ms = kFakeCaptureTimeoutMs * frame_count_;
139 int milliseconds = elapsed_ms % 1000;
140 int seconds = (elapsed_ms / 1000) % 60;
141 int minutes = (elapsed_ms / 1000 / 60) % 60;
142 int hours = (elapsed_ms / 1000 / 60 / 60) % 60;
144 std::string time_string =
145 base::StringPrintf("%d:%02d:%02d:%03d %d", hours, minutes,
146 seconds, milliseconds, frame_count_);
147 canvas.scale(3, 3);
148 canvas.drawText(time_string.data(), time_string.length(), 30, 20,
149 paint);
151 if (frame_count_ % kFakeCaptureBeepCycle == 0) {
152 // Generate a synchronized beep sound if there is one audio input
153 // stream created.
154 FakeAudioInputStream::BeepOnce();
157 frame_count_++;
159 // Give the captured frame to the client.
160 client_->OnIncomingCapturedData(fake_frame_.get(),
161 frame_size,
162 capture_format_,
164 base::TimeTicks::Now());
165 if (!(frame_count_ % kFakeCaptureCapabilityChangePeriod) &&
166 format_roster_.size() > 0U) {
167 Reallocate();
169 // Reschedule next CaptureTask.
170 capture_thread_.message_loop()->PostDelayedTask(
171 FROM_HERE,
172 base::Bind(&FakeVideoCaptureDevice::OnCaptureTask,
173 base::Unretained(this)),
174 base::TimeDelta::FromMilliseconds(kFakeCaptureTimeoutMs));
177 void FakeVideoCaptureDevice::Reallocate() {
178 DCHECK_EQ(capture_thread_.message_loop(), base::MessageLoop::current());
179 capture_format_ =
180 format_roster_.at(++format_roster_index_ % format_roster_.size());
181 DCHECK_EQ(capture_format_.pixel_format, PIXEL_FORMAT_I420);
182 DVLOG(3) << "Reallocating FakeVideoCaptureDevice, new capture resolution "
183 << capture_format_.frame_size.ToString();
185 const size_t fake_frame_size =
186 VideoFrame::AllocationSize(VideoFrame::I420, capture_format_.frame_size);
187 fake_frame_.reset(new uint8[fake_frame_size]);
190 } // namespace media