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

Side by Side Diff: content/renderer/media/video_capture_impl.cc

Issue 7071002: Revert "Add VideoCaptureImpl and VideoCaptureImplManager" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 7 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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.
4
5 #include "content/renderer/media/video_capture_impl.h"
6
7 #include "content/common/child_process.h"
8 #include "content/common/video_capture_messages.h"
9
10 VideoCaptureImpl::DIBBuffer::DIBBuffer(
11 TransportDIB* d, media::VideoCapture::VideoFrameBuffer* ptr)
12 : dib(d),
13 mapped_memory(ptr) {}
14
15 VideoCaptureImpl::DIBBuffer::~DIBBuffer() {
16 delete dib;
17 }
18
19 bool VideoCaptureImpl::CaptureStarted() {
20 return state_ == kStarted;
21 }
22
23 int VideoCaptureImpl::CaptureWidth() {
24 return width_;
25 }
26
27 int VideoCaptureImpl::CaptureHeight() {
28 return height_;
29 }
30
31 int VideoCaptureImpl::CaptureFrameRate() {
32 return frame_rate_;
33 }
34
35 VideoCaptureImpl::VideoCaptureImpl(
36 const media::VideoCaptureSessionId id,
37 scoped_refptr<base::MessageLoopProxy> ml_proxy,
38 VideoCaptureMessageFilter* filter)
39 : VideoCapture(),
40 message_filter_(filter),
41 session_id_(id),
42 ml_proxy_(ml_proxy),
43 device_id_(0),
44 width_(0),
45 height_(0),
46 frame_rate_(0),
47 video_type_(media::VideoFrame::I420),
48 new_width_(0),
49 new_height_(0),
50 state_(kStopped) {
51 DCHECK(filter);
52 }
53
54 VideoCaptureImpl::~VideoCaptureImpl() {}
55
56 void VideoCaptureImpl::Init() {
57 base::MessageLoopProxy* io_message_loop_proxy =
58 ChildProcess::current()->io_message_loop_proxy();
59
60 if (!io_message_loop_proxy->BelongsToCurrentThread()) {
61 io_message_loop_proxy->PostTask(FROM_HERE,
62 NewRunnableMethod(this, &VideoCaptureImpl::AddDelegateOnIOThread));
63 return;
64 }
65
66 AddDelegateOnIOThread();
67 }
68
69 void VideoCaptureImpl::DeInit(Task* task) {
70 if (state_ == kStarted)
71 message_filter_->Send(new VideoCaptureHostMsg_Stop(0, device_id_));
72
73 base::MessageLoopProxy* io_message_loop_proxy =
74 ChildProcess::current()->io_message_loop_proxy();
75
76 if (!io_message_loop_proxy->BelongsToCurrentThread()) {
77 io_message_loop_proxy->PostTask(FROM_HERE,
78 NewRunnableMethod(this, &VideoCaptureImpl::RemoveDelegateOnIOThread,
79 task));
80 return;
81 }
82
83 RemoveDelegateOnIOThread(task);
84 }
85
86 void VideoCaptureImpl::StartCapture(
87 media::VideoCapture::EventHandler* handler,
88 const VideoCaptureCapability& capability) {
89 DCHECK_EQ(capability.raw_type, media::VideoFrame::I420);
90
91 if (!ml_proxy_->BelongsToCurrentThread()) {
92 ml_proxy_->PostTask(FROM_HERE,
93 NewRunnableMethod(this, &VideoCaptureImpl::StartCapture, handler,
94 capability));
95 return;
96 }
97
98 ClientInfo::iterator it = pending_clients_.find(handler);
99
100 if (it != pending_clients_.end()) {
101 handler->OnError(this, 1);
102 return;
103 }
104
105 if (!device_id_) {
106 pending_clients_[handler] = capability;
107 return;
108 }
109
110 if (capability.resolution_fixed && master_clients_.size() &&
111 (capability.width != width_ || capability.height != height_)) {
112 // Can't have 2 master clients with different resolutions.
113 handler->OnError(this, 1);
114 return;
115 }
116
117 clients_[handler] = capability;
118 if (capability.resolution_fixed) {
119 master_clients_.push_back(handler);
120 if (master_clients_.size() > 1)
121 return;
122 }
123
124 if (state_ == kStarted) {
125 // Take the resolution of master client.
126 if (capability.resolution_fixed &&
127 (capability.width != width_ || capability.height != height_)) {
128 new_width_ = capability.width;
129 new_height_ = capability.height;
130 DLOG(INFO) << "StartCapture: Got master client with new resolution "
131 "during started, try to restart.";
132 StopDevice();
133 }
134 handler->OnStarted(this);
135 return;
136 }
137
138 if (state_ == kStopping) {
139 if (capability.resolution_fixed || !pending_start()) {
140 new_width_ = capability.width;
141 new_height_ = capability.height;
142 DLOG(INFO) << "StartCapture: Got new resolution, already in stopping.";
143 }
144 handler->OnStarted(this);
145 return;
146 }
147
148 DCHECK_EQ(clients_.size(), 1ul);
149 video_type_ = capability.raw_type;
150 new_width_ = 0;
151 new_height_ = 0;
152 width_ = capability.width;
153 height_ = capability.height;
154
155 StartCaptureInternal();
156 }
157
158 void VideoCaptureImpl::StopCapture(media::VideoCapture::EventHandler* handler) {
159 if (!ml_proxy_->BelongsToCurrentThread()) {
160 ml_proxy_->PostTask(FROM_HERE,
161 NewRunnableMethod(this, &VideoCaptureImpl::StopCapture, handler));
162 return;
163 }
164
165 ClientInfo::iterator it = pending_clients_.find(handler);
166 if (it != pending_clients_.end()) {
167 handler->OnStopped(this);
168 pending_clients_.erase(it);
169 return;
170 }
171
172 if (clients_.find(handler) == clients_.end())
173 return;
174
175 handler->OnStopped(this);
176 clients_.erase(handler);
177 master_clients_.remove(handler);
178
179 // Still have at least one master client.
180 if (master_clients_.size() > 0)
181 return;
182
183 // TODO(wjia): Is it really needed to handle resolution change for non-master
184 // clients, except no client case?
185 if (clients_.size() > 0) {
186 DLOG(INFO) << "StopCapture: No master client.";
187 int maxw = 0;
188 int maxh = 0;
189 for (ClientInfo::iterator it = clients_.begin();
190 it != clients_.end(); it++) {
191 if (it->second.width > maxw && it->second.height > maxh) {
192 maxw = it->second.width;
193 maxh = it->second.height;
194 }
195 }
196
197 if (state_ == kStarted) {
198 // Only handle resolution reduction.
199 if (maxw < width_ && maxh < height_) {
200 new_width_ = maxw;
201 new_height_ = maxh;
202 DLOG(INFO) << "StopCapture: New smaller resolution, stopping ...";
203 StopDevice();
204 }
205 return;
206 }
207
208 if (state_ == kStopping) {
209 new_width_ = maxw;
210 new_height_ = maxh;
211 DLOG(INFO) << "StopCapture: New resolution, during stopping.";
212 return;
213 }
214 } else {
215 new_width_ = width_ = 0;
216 new_height_ = height_ = 0;
217 DLOG(INFO) << "StopCapture: No more client, stopping ...";
218 StopDevice();
219 }
220 }
221
222 void VideoCaptureImpl::OnBufferReceived(TransportDIB::Handle handle,
223 base::Time timestamp) {
224 if (!ml_proxy_->BelongsToCurrentThread()) {
225 ml_proxy_->PostTask(FROM_HERE,
226 NewRunnableMethod(this, &VideoCaptureImpl::OnBufferReceived,
227 handle, timestamp));
228 return;
229 }
230
231 if (state_ != kStarted) {
232 message_filter_->Send(
233 new VideoCaptureHostMsg_BufferReady(0, device_id_, handle));
234 return;
235 }
236
237 media::VideoCapture::VideoFrameBuffer* buffer;
238 CachedDIB::iterator it;
239 for (it = cached_dibs_.begin(); it != cached_dibs_.end(); it++) {
240 if ((*it)->dib->handle() == handle)
241 break;
242 }
243 if (it == cached_dibs_.end()) {
244 TransportDIB* dib = TransportDIB::Map(handle);
245 buffer = new VideoFrameBuffer();
246 buffer->memory_pointer = dib->memory();
247 buffer->buffer_size = dib->size();
248 buffer->width = width_;
249 buffer->height = height_;
250
251 DIBBuffer* dib_buffer = new DIBBuffer(dib, buffer);
252 cached_dibs_.push_back(dib_buffer);
253 } else {
254 buffer = (*it)->mapped_memory;
255 }
256
257 // TODO(wjia): handle buffer sharing with downstream modules.
258 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) {
259 it->first->OnBufferReady(this, buffer);
260 }
261
262 message_filter_->Send(
263 new VideoCaptureHostMsg_BufferReady(0, device_id_, handle));
264 }
265
266 void VideoCaptureImpl::OnStateChanged(
267 const media::VideoCapture::State& state) {
268 if (!ml_proxy_->BelongsToCurrentThread()) {
269 ml_proxy_->PostTask(FROM_HERE,
270 NewRunnableMethod(this, &VideoCaptureImpl::OnStateChanged, state));
271 return;
272 }
273
274 switch (state) {
275 case media::VideoCapture::kStarted:
276 for (ClientInfo::iterator it = clients_.begin();
277 it != clients_.end(); it++) {
278 it->first->OnStarted(this);
279 }
280 break;
281 case media::VideoCapture::kStopped:
282 state_ = kStopped;
283 DLOG(INFO) << "OnStateChanged: stopped!, device_id = " << device_id_;
284 if (pending_start())
285 RestartCapture();
286 break;
287 case media::VideoCapture::kPaused:
288 for (ClientInfo::iterator it = clients_.begin();
289 it != clients_.end(); it++) {
290 it->first->OnPaused(this);
291 }
292 break;
293 case media::VideoCapture::kError:
294 for (ClientInfo::iterator it = clients_.begin();
295 it != clients_.end(); it++) {
296 // TODO(wjia): browser process would send error code.
297 it->first->OnError(this, 1);
298 }
299 break;
300 default:
301 break;
302 }
303 }
304
305 void VideoCaptureImpl::OnDeviceInfoReceived(
306 const media::VideoCaptureParams& device_info) {
307 if (!ml_proxy_->BelongsToCurrentThread()) {
308 ml_proxy_->PostTask(FROM_HERE,
309 NewRunnableMethod(this, &VideoCaptureImpl::OnDeviceInfoReceived,
310 device_info));
311 return;
312 }
313
314 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) {
315 it->first->OnDeviceInfoReceived(this, device_info);
316 }
317 }
318
319 void VideoCaptureImpl::OnDelegateAdded(int32 device_id) {
320 if (!ml_proxy_->BelongsToCurrentThread()) {
321 ml_proxy_->PostTask(FROM_HERE,
322 NewRunnableMethod(this, &VideoCaptureImpl::OnDelegateAdded, device_id));
323 return;
324 }
325
326 device_id_ = device_id;
327 for (ClientInfo::iterator it = pending_clients_.begin();
328 it != pending_clients_.end(); ) {
329 media::VideoCapture::EventHandler* handler = it->first;
330 const VideoCaptureCapability capability = it->second;
331 pending_clients_.erase(it++);
332 StartCapture(handler, capability);
333 }
334 }
335
336 void VideoCaptureImpl::StopDevice() {
337 if (!ml_proxy_->BelongsToCurrentThread()) {
338 ml_proxy_->PostTask(FROM_HERE,
339 NewRunnableMethod(this, &VideoCaptureImpl::StopDevice));
340 return;
341 }
342
343 if (state_ == kStarted) {
344 state_ = kStopping;
345 message_filter_->Send(new VideoCaptureHostMsg_Stop(0, device_id_));
346 width_ = height_ = 0;
347 }
348 }
349
350 void VideoCaptureImpl::RestartCapture() {
351 DCHECK(ml_proxy_->BelongsToCurrentThread());
352 DCHECK_EQ(state_, kStopped);
353
354 width_ = new_width_;
355 height_ = new_height_;
356 new_width_ = 0;
357 new_height_ = 0;
358
359 DLOG(INFO) << "RestartCapture, " << width_ << ", " << height_;
360 StartCaptureInternal();
361 }
362
363 void VideoCaptureImpl::StartCaptureInternal() {
364 DCHECK(ml_proxy_->BelongsToCurrentThread());
365 DCHECK(device_id_);
366
367 media::VideoCaptureParams params;
368 params.width = width_;
369 params.height = height_;
370 params.session_id = session_id_;
371
372 message_filter_->Send(new VideoCaptureHostMsg_Start(0, device_id_, params));
373 state_ = kStarted;
374 for (ClientInfo::iterator it = clients_.begin(); it != clients_.end(); it++) {
375 it->first->OnStarted(this);
376 }
377 }
378
379 void VideoCaptureImpl::AddDelegateOnIOThread() {
380 message_filter_->AddDelegate(this);
381 }
382
383 void VideoCaptureImpl::RemoveDelegateOnIOThread(Task* task) {
384 message_filter_->RemoveDelegate(this);
385 media::AutoTaskRunner auto_runner(task);
386 }
OLDNEW
« no previous file with comments | « content/renderer/media/video_capture_impl.h ('k') | content/renderer/media/video_capture_impl_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698