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

Side by Side Diff: content/browser/renderer_host/media/video_capture_controller.cc

Issue 23551011: From Video Capture, abolish OnFrameInfo and enable resolution changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixes from bbudge Created 7 years, 2 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
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 "content/browser/renderer_host/media/video_capture_controller.h" 5 #include "content/browser/renderer_host/media/video_capture_controller.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 ~ControllerClient() {} 42 ~ControllerClient() {}
43 43
44 // ID used for identifying this object. 44 // ID used for identifying this object.
45 VideoCaptureControllerID controller_id; 45 VideoCaptureControllerID controller_id;
46 VideoCaptureControllerEventHandler* event_handler; 46 VideoCaptureControllerEventHandler* event_handler;
47 47
48 // Handle to the render process that will receive the capture buffers. 48 // Handle to the render process that will receive the capture buffers.
49 base::ProcessHandle render_process_handle; 49 base::ProcessHandle render_process_handle;
50 media::VideoCaptureParams parameters; 50 media::VideoCaptureParams parameters;
51 51
52 // Buffers used by this client. 52 // Buffers that are currently known to this client.
53 std::set<int> buffers; 53 std::set<int> known_buffers;
54
55 // Buffers currently held by this client.
56 std::set<int> active_buffers;
54 57
55 // State of capture session, controlled by VideoCaptureManager directly. This 58 // State of capture session, controlled by VideoCaptureManager directly. This
56 // transitions to true as soon as StopSession() occurs, at which point the 59 // transitions to true as soon as StopSession() occurs, at which point the
57 // client is sent an OnEnded() event. However, because the client retains a 60 // client is sent an OnEnded() event. However, because the client retains a
58 // VideoCaptureController* pointer, its ControllerClient entry lives on until 61 // VideoCaptureController* pointer, its ControllerClient entry lives on until
59 // it unregisters itself via RemoveClient(), which may happen asynchronously. 62 // it unregisters itself via RemoveClient(), which may happen asynchronously.
60 // 63 //
61 // TODO(nick): If we changed the semantics of VideoCaptureHost so that 64 // TODO(nick): If we changed the semantics of VideoCaptureHost so that
62 // OnEnded() events were processed synchronously (with the RemoveClient() done 65 // OnEnded() events were processed synchronously (with the RemoveClient() done
63 // implicitly), we could avoid tracking this state here in the Controller, and 66 // implicitly), we could avoid tracking this state here in the Controller, and
64 // simplify the code in both places. 67 // simplify the code in both places.
65 bool session_closed; 68 bool session_closed;
66 }; 69 };
67 70
68 // Receives events from the VideoCaptureDevice and posts them to a 71 // Receives events from the VideoCaptureDevice and posts them to a
69 // VideoCaptureController on the IO thread. An instance of this class may safely 72 // VideoCaptureController on the IO thread. An instance of this class may safely
70 // outlive its target VideoCaptureController. 73 // outlive its target VideoCaptureController.
71 // 74 //
72 // Methods of this class may be called from any thread, and in practice will 75 // Methods of this class may be called from any thread, and in practice will
73 // often be called on some auxiliary thread depending on the platform and the 76 // often be called on some auxiliary thread depending on the platform and the
74 // device type; including, for example, the DirectShow thread on Windows, the 77 // device type; including, for example, the DirectShow thread on Windows, the
75 // v4l2_thread on Linux, and the UI thread for tab capture. 78 // v4l2_thread on Linux, and the UI thread for tab capture.
76 class VideoCaptureController::VideoCaptureDeviceClient 79 class VideoCaptureController::VideoCaptureDeviceClient
77 : public media::VideoCaptureDevice::Client { 80 : public media::VideoCaptureDevice::Client {
78 public: 81 public:
79 explicit VideoCaptureDeviceClient( 82 explicit VideoCaptureDeviceClient(
80 const base::WeakPtr<VideoCaptureController>& controller); 83 const base::WeakPtr<VideoCaptureController>& controller,
84 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool);
81 virtual ~VideoCaptureDeviceClient(); 85 virtual ~VideoCaptureDeviceClient();
82 86
83 // VideoCaptureDevice::Client implementation. 87 // VideoCaptureDevice::Client implementation.
84 virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE; 88 virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer(
89 const gfx::Size& size) OVERRIDE;
85 virtual void OnIncomingCapturedFrame(const uint8* data, 90 virtual void OnIncomingCapturedFrame(const uint8* data,
86 int length, 91 int length,
87 base::Time timestamp, 92 base::Time timestamp,
88 int rotation, 93 int rotation,
89 bool flip_vert, 94 bool flip_vert,
90 bool flip_horiz) OVERRIDE; 95 bool flip_horiz) OVERRIDE;
91 virtual void OnIncomingCapturedVideoFrame( 96 virtual void OnIncomingCapturedVideoFrame(
92 const scoped_refptr<media::VideoFrame>& frame, 97 const scoped_refptr<media::VideoFrame>& frame,
93 base::Time timestamp) OVERRIDE; 98 base::Time timestamp) OVERRIDE;
94 virtual void OnError() OVERRIDE; 99 virtual void OnError() OVERRIDE;
95 virtual void OnFrameInfo( 100 virtual void OnFrameInfo(
96 const media::VideoCaptureCapability& info) OVERRIDE; 101 const media::VideoCaptureCapability& info) OVERRIDE;
97 virtual void OnFrameInfoChanged( 102 virtual void OnFrameInfoChanged(
98 const media::VideoCaptureCapability& info) OVERRIDE; 103 const media::VideoCaptureCapability& info) OVERRIDE;
99 104
100 private: 105 private:
106 scoped_refptr<media::VideoFrame> DoReserveI420VideoFrame(
107 const gfx::Size& size,
108 int rotation);
109
101 // The controller to which we post events. 110 // The controller to which we post events.
102 const base::WeakPtr<VideoCaptureController> controller_; 111 const base::WeakPtr<VideoCaptureController> controller_;
103 112
104 // The pool of shared-memory buffers used for capturing. 113 // The pool of shared-memory buffers used for capturing.
105 scoped_refptr<VideoCaptureBufferPool> buffer_pool_; 114 const scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
106 115
107 // Chopped pixels in width/height in case video capture device has odd 116 // Chopped pixels in width/height in case video capture device has odd
108 // numbers for width/height. 117 // numbers for width/height.
109 int chopped_width_; 118 int chopped_width_;
110 int chopped_height_; 119 int chopped_height_;
111 120
112 // Tracks the current frame format. 121 // Tracks the current frame format.
113 media::VideoCaptureCapability frame_info_; 122 media::VideoCaptureCapability frame_info_;
114 }; 123 };
115 124
116 VideoCaptureController::VideoCaptureController() 125 VideoCaptureController::VideoCaptureController()
117 : state_(VIDEO_CAPTURE_STATE_STARTED), 126 : buffer_pool_(new VideoCaptureBufferPool(kNoOfBuffers)),
127 state_(VIDEO_CAPTURE_STATE_STARTED),
118 weak_ptr_factory_(this) { 128 weak_ptr_factory_(this) {
119 memset(&current_params_, 0, sizeof(current_params_));
120 } 129 }
121 130
122 VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient( 131 VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient(
123 const base::WeakPtr<VideoCaptureController>& controller) 132 const base::WeakPtr<VideoCaptureController>& controller,
133 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool)
124 : controller_(controller), 134 : controller_(controller),
135 buffer_pool_(buffer_pool),
125 chopped_width_(0), 136 chopped_width_(0),
126 chopped_height_(0) {} 137 chopped_height_(0) {}
127 138
128 VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {} 139 VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {}
129 140
130 base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() { 141 base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() {
131 return weak_ptr_factory_.GetWeakPtr(); 142 return weak_ptr_factory_.GetWeakPtr();
132 } 143 }
133 144
134 scoped_ptr<media::VideoCaptureDevice::Client> 145 scoped_ptr<media::VideoCaptureDevice::Client>
135 VideoCaptureController::NewDeviceClient() { 146 VideoCaptureController::NewDeviceClient() {
136 scoped_ptr<media::VideoCaptureDevice::Client> result( 147 scoped_ptr<media::VideoCaptureDevice::Client> result(
137 new VideoCaptureDeviceClient(this->GetWeakPtr())); 148 new VideoCaptureDeviceClient(this->GetWeakPtr(), buffer_pool_));
138 return result.Pass(); 149 return result.Pass();
139 } 150 }
140 151
141 void VideoCaptureController::AddClient( 152 void VideoCaptureController::AddClient(
142 const VideoCaptureControllerID& id, 153 const VideoCaptureControllerID& id,
143 VideoCaptureControllerEventHandler* event_handler, 154 VideoCaptureControllerEventHandler* event_handler,
144 base::ProcessHandle render_process, 155 base::ProcessHandle render_process,
145 const media::VideoCaptureParams& params) { 156 const media::VideoCaptureParams& params) {
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
147 DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id 158 DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id
148 << ", (" << params.width 159 << ", (" << params.requested_format.width
149 << ", " << params.height 160 << ", " << params.requested_format.height
150 << ", " << params.frame_rate 161 << ", " << params.requested_format.frame_rate
151 << ", " << params.session_id 162 << ", " << params.session_id
152 << ")"; 163 << ")";
153 164
154 // Signal error in case device is already in error state. 165 // Signal error in case device is already in error state.
155 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { 166 if (state_ == VIDEO_CAPTURE_STATE_ERROR) {
156 event_handler->OnError(id); 167 event_handler->OnError(id);
157 return; 168 return;
158 } 169 }
159 170
160 // Do nothing if this client has called AddClient before. 171 // Do nothing if this client has called AddClient before.
161 if (FindClient(id, event_handler, controller_clients_)) 172 if (FindClient(id, event_handler, controller_clients_))
162 return; 173 return;
163 174
164 ControllerClient* client = new ControllerClient(id, event_handler, 175 ControllerClient* client = new ControllerClient(id, event_handler,
165 render_process, params); 176 render_process, params);
166 // If we already have gotten frame_info from the device, repeat it to the new 177 // If we already have gotten frame_info from the device, repeat it to the new
167 // client. 178 // client.
168 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 179 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
169 if (frame_info_.IsValid()) {
170 SendFrameInfoAndBuffers(client);
171 }
172 controller_clients_.push_back(client); 180 controller_clients_.push_back(client);
173 return; 181 return;
174 } 182 }
175 } 183 }
176 184
177 int VideoCaptureController::RemoveClient( 185 int VideoCaptureController::RemoveClient(
178 const VideoCaptureControllerID& id, 186 const VideoCaptureControllerID& id,
179 VideoCaptureControllerEventHandler* event_handler) { 187 VideoCaptureControllerEventHandler* event_handler) {
180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
181 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id; 189 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id;
182 190
183 ControllerClient* client = FindClient(id, event_handler, controller_clients_); 191 ControllerClient* client = FindClient(id, event_handler, controller_clients_);
184 if (!client) 192 if (!client)
185 return kInvalidMediaCaptureSessionId; 193 return kInvalidMediaCaptureSessionId;
186 194
187 // Take back all buffers held by the |client|. 195 // Take back all buffers held by the |client|.
188 if (buffer_pool_.get()) { 196 for (std::set<int>::iterator buffer_it = client->active_buffers.begin();
189 for (std::set<int>::iterator buffer_it = client->buffers.begin(); 197 buffer_it != client->active_buffers.end();
190 buffer_it != client->buffers.end(); 198 ++buffer_it) {
191 ++buffer_it) { 199 int buffer_id = *buffer_it;
192 int buffer_id = *buffer_it; 200 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
193 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
194 }
195 } 201 }
196 client->buffers.clear(); 202 client->active_buffers.clear();
197 203
198 int session_id = client->parameters.session_id; 204 int session_id = client->parameters.session_id;
199 controller_clients_.remove(client); 205 controller_clients_.remove(client);
200 delete client; 206 delete client;
201 207
202 return session_id; 208 return session_id;
203 } 209 }
204 210
205 void VideoCaptureController::StopSession(int session_id) { 211 void VideoCaptureController::StopSession(int session_id) {
206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
(...skipping 10 matching lines...) Expand all
217 void VideoCaptureController::ReturnBuffer( 223 void VideoCaptureController::ReturnBuffer(
218 const VideoCaptureControllerID& id, 224 const VideoCaptureControllerID& id,
219 VideoCaptureControllerEventHandler* event_handler, 225 VideoCaptureControllerEventHandler* event_handler,
220 int buffer_id) { 226 int buffer_id) {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
222 228
223 ControllerClient* client = FindClient(id, event_handler, controller_clients_); 229 ControllerClient* client = FindClient(id, event_handler, controller_clients_);
224 230
225 // If this buffer is not held by this client, or this client doesn't exist 231 // If this buffer is not held by this client, or this client doesn't exist
226 // in controller, do nothing. 232 // in controller, do nothing.
227 if (!client || 233 if (!client || !client->active_buffers.erase(buffer_id)) {
228 client->buffers.find(buffer_id) == client->buffers.end()) {
229 NOTREACHED(); 234 NOTREACHED();
230 return; 235 return;
231 } 236 }
232 237
233 client->buffers.erase(buffer_id);
234 buffer_pool_->RelinquishConsumerHold(buffer_id, 1); 238 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
235 } 239 }
236 240
237 scoped_refptr<media::VideoFrame> 241 scoped_refptr<media::VideoFrame>
238 VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer() { 242 VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer(
239 return buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width, 243 const gfx::Size& size) {
240 frame_info_.height), 244 return DoReserveI420VideoFrame(size, 0);
241 0);
242 } 245 }
243 246
244 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( 247 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
245 const uint8* data, 248 const uint8* data,
246 int length, 249 int length,
247 base::Time timestamp, 250 base::Time timestamp,
248 int rotation, 251 int rotation,
249 bool flip_vert, 252 bool flip_vert,
250 bool flip_horiz) { 253 bool flip_horiz) {
251 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); 254 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
252 255
253 if (!buffer_pool_.get()) 256 if (!frame_info_.IsValid())
254 return; 257 return;
255 scoped_refptr<media::VideoFrame> dst = buffer_pool_->ReserveI420VideoFrame( 258
259 scoped_refptr<media::VideoFrame> dst = DoReserveI420VideoFrame(
256 gfx::Size(frame_info_.width, frame_info_.height), rotation); 260 gfx::Size(frame_info_.width, frame_info_.height), rotation);
257 261
258 if (!dst.get()) 262 if (!dst.get())
259 return; 263 return;
260 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) 264 #if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW)
261 265
262 uint8* yplane = dst->data(media::VideoFrame::kYPlane); 266 uint8* yplane = dst->data(media::VideoFrame::kYPlane);
263 uint8* uplane = dst->data(media::VideoFrame::kUPlane); 267 uint8* uplane = dst->data(media::VideoFrame::kUPlane);
264 uint8* vplane = dst->data(media::VideoFrame::kVPlane); 268 uint8* vplane = dst->data(media::VideoFrame::kVPlane);
265 int yplane_stride = frame_info_.width; 269 int yplane_stride = frame_info_.width;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 // not used in those builds either. Whenever libyuv is added in that build, 384 // not used in those builds either. Whenever libyuv is added in that build,
381 // address all these #ifdef parts, see http://crbug.com/299611 . 385 // address all these #ifdef parts, see http://crbug.com/299611 .
382 NOTREACHED(); 386 NOTREACHED();
383 #endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW) 387 #endif // if !defined(AVOID_LIBYUV_FOR_ANDROID_WEBVIEW)
384 BrowserThread::PostTask( 388 BrowserThread::PostTask(
385 BrowserThread::IO, 389 BrowserThread::IO,
386 FROM_HERE, 390 FROM_HERE,
387 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 391 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
388 controller_, 392 controller_,
389 dst, 393 dst,
394 frame_info_.frame_rate,
390 timestamp)); 395 timestamp));
391 } 396 }
392 397
393 void 398 void
394 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( 399 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
395 const scoped_refptr<media::VideoFrame>& frame, 400 const scoped_refptr<media::VideoFrame>& frame,
396 base::Time timestamp) { 401 base::Time timestamp) {
397 if (!buffer_pool_)
398 return;
399 402
400 // If this is a frame that belongs to the buffer pool, we can forward it 403 // If this is a frame that belongs to the buffer pool, we can forward it
401 // directly to the IO thread and be done. 404 // directly to the IO thread and be done.
402 if (buffer_pool_->RecognizeReservedBuffer( 405 if (buffer_pool_->RecognizeReservedBuffer(
403 frame->shared_memory_handle()) >= 0) { 406 frame->shared_memory_handle()) >= 0) {
404 BrowserThread::PostTask(BrowserThread::IO, 407 BrowserThread::PostTask(BrowserThread::IO,
405 FROM_HERE, 408 FROM_HERE,
406 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 409 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
407 controller_, frame, timestamp)); 410 controller_, frame, frame_info_.frame_rate, timestamp));
408 return; 411 return;
409 } 412 }
410 413
411 // Otherwise, this is a frame that belongs to the caller, and we must copy 414 NOTREACHED() << "Frames should always belong to the buffer pool.";
412 // it to a frame from the buffer pool.
413 scoped_refptr<media::VideoFrame> target =
414 buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
415 frame_info_.height),
416 0);
417
418 if (!target.get())
419 return;
420
421 // Validate the inputs.
422 if (frame->coded_size() != target->coded_size())
423 return; // Only exact copies are supported.
424 if (!(frame->format() == media::VideoFrame::I420 ||
425 frame->format() == media::VideoFrame::YV12 ||
426 frame->format() == media::VideoFrame::RGB32)) {
427 NOTREACHED() << "Unsupported format passed to OnIncomingCapturedVideoFrame";
428 return;
429 }
430
431 const int kYPlane = media::VideoFrame::kYPlane;
432 const int kUPlane = media::VideoFrame::kUPlane;
433 const int kVPlane = media::VideoFrame::kVPlane;
434 const int kAPlane = media::VideoFrame::kAPlane;
435 const int kRGBPlane = media::VideoFrame::kRGBPlane;
436
437 // Do color conversion from the camera format to I420.
438 switch (frame->format()) {
439 #if defined(GOOGLE_TV)
440 case media::VideoFrame::HOLE:
441 // Fall-through to NOTREACHED() block.
442 #endif
443 case media::VideoFrame::INVALID:
444 case media::VideoFrame::YV16:
445 case media::VideoFrame::EMPTY:
446 case media::VideoFrame::NATIVE_TEXTURE: {
447 NOTREACHED();
448 break;
449 }
450 case media::VideoFrame::I420:
451 case media::VideoFrame::YV12: {
452 DCHECK(!chopped_width_ && !chopped_height_);
453 media::CopyYPlane(frame->data(kYPlane),
454 frame->stride(kYPlane),
455 frame->rows(kYPlane),
456 target.get());
457 media::CopyUPlane(frame->data(kUPlane),
458 frame->stride(kUPlane),
459 frame->rows(kUPlane),
460 target.get());
461 media::CopyVPlane(frame->data(kVPlane),
462 frame->stride(kVPlane),
463 frame->rows(kVPlane),
464 target.get());
465 break;
466 }
467 case media::VideoFrame::YV12A: {
468 DCHECK(!chopped_width_ && !chopped_height_);
469 media::CopyYPlane(frame->data(kYPlane),
470 frame->stride(kYPlane),
471 frame->rows(kYPlane),
472 target.get());
473 media::CopyUPlane(frame->data(kUPlane),
474 frame->stride(kUPlane),
475 frame->rows(kUPlane),
476 target.get());
477 media::CopyVPlane(frame->data(kVPlane),
478 frame->stride(kVPlane),
479 frame->rows(kVPlane),
480 target.get());
481 media::CopyAPlane(frame->data(kAPlane),
482 frame->stride(kAPlane),
483 frame->rows(kAPlane),
484 target.get());
485 break;
486 }
487 case media::VideoFrame::RGB32: {
488 media::ConvertRGB32ToYUV(frame->data(kRGBPlane),
489 target->data(kYPlane),
490 target->data(kUPlane),
491 target->data(kVPlane),
492 target->coded_size().width(),
493 target->coded_size().height(),
494 frame->stride(kRGBPlane),
495 target->stride(kYPlane),
496 target->stride(kUPlane));
497 break;
498 }
499 }
500
501 BrowserThread::PostTask(BrowserThread::IO,
502 FROM_HERE,
503 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
504 controller_, target, timestamp));
505 } 415 }
506 416
507 void VideoCaptureController::VideoCaptureDeviceClient::OnError() { 417 void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
508 BrowserThread::PostTask(BrowserThread::IO, 418 BrowserThread::PostTask(BrowserThread::IO,
509 FROM_HERE, 419 FROM_HERE,
510 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); 420 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
511 } 421 }
512 422
513 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo( 423 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo(
514 const media::VideoCaptureCapability& info) { 424 const media::VideoCaptureCapability& info) {
515 frame_info_ = info; 425 frame_info_ = info;
516 // Handle cases when |info| has odd numbers for width/height. 426 // Handle cases when |info| has odd numbers for width/height.
517 if (info.width & 1) { 427 if (info.width & 1) {
518 --frame_info_.width; 428 --frame_info_.width;
519 chopped_width_ = 1; 429 chopped_width_ = 1;
520 } else { 430 } else {
521 chopped_width_ = 0; 431 chopped_width_ = 0;
522 } 432 }
523 if (info.height & 1) { 433 if (info.height & 1) {
524 --frame_info_.height; 434 --frame_info_.height;
525 chopped_height_ = 1; 435 chopped_height_ = 1;
526 } else { 436 } else {
527 chopped_height_ = 0; 437 chopped_height_ = 0;
528 } 438 }
529
530 DCHECK(!buffer_pool_.get());
531
532 // TODO(nick): Give BufferPool the same lifetime as the controller, have it
533 // support frame size changes, and stop checking it for NULL everywhere.
534 // http://crbug.com/266082
535 buffer_pool_ = new VideoCaptureBufferPool(
536 media::VideoFrame::AllocationSize(
537 media::VideoFrame::I420,
538 gfx::Size(frame_info_.width, frame_info_.height)),
539 kNoOfBuffers);
540
541 // Check whether all buffers were created successfully.
542 if (!buffer_pool_->Allocate()) {
543 // Transition to the error state.
544 buffer_pool_ = NULL;
545 OnError();
546 return;
547 }
548
549 BrowserThread::PostTask(BrowserThread::IO,
550 FROM_HERE,
551 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, controller_,
552 frame_info_, buffer_pool_));
553 } 439 }
554 440
555 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged( 441 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged(
556 const media::VideoCaptureCapability& info) { 442 const media::VideoCaptureCapability& info) {
557 BrowserThread::PostTask(BrowserThread::IO, 443 OnFrameInfo(info);
558 FROM_HERE, 444 }
559 base::Bind(&VideoCaptureController::DoFrameInfoChangedOnIOThread, 445
560 controller_, info)); 446 scoped_refptr<media::VideoFrame>
447 VideoCaptureController::VideoCaptureDeviceClient::DoReserveI420VideoFrame(
448 const gfx::Size& size,
449 int rotation) {
450 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
451 scoped_refptr<media::VideoFrame> frame =
452 buffer_pool_->ReserveI420VideoFrame(size, rotation, &buffer_id_to_drop);
453 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) {
454 BrowserThread::PostTask(BrowserThread::IO,
455 FROM_HERE,
456 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread,
457 controller_, buffer_id_to_drop));
458 }
459 return frame;
561 } 460 }
562 461
563 VideoCaptureController::~VideoCaptureController() { 462 VideoCaptureController::~VideoCaptureController() {
564 buffer_pool_ = NULL; // Release all buffers.
565 STLDeleteContainerPointers(controller_clients_.begin(), 463 STLDeleteContainerPointers(controller_clients_.begin(),
566 controller_clients_.end()); 464 controller_clients_.end());
567 } 465 }
568 466
569 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( 467 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
570 const scoped_refptr<media::VideoFrame>& reserved_frame, 468 const scoped_refptr<media::VideoFrame>& reserved_frame,
469 int frame_rate,
571 base::Time timestamp) { 470 base::Time timestamp) {
572 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 471 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
573 472
574 if (!buffer_pool_.get())
575 return;
576
577 int buffer_id = buffer_pool_->RecognizeReservedBuffer( 473 int buffer_id = buffer_pool_->RecognizeReservedBuffer(
578 reserved_frame->shared_memory_handle()); 474 reserved_frame->shared_memory_handle());
579 if (buffer_id < 0) { 475 if (buffer_id < 0) {
580 NOTREACHED(); 476 NOTREACHED();
581 return; 477 return;
582 } 478 }
583 479
480 media::VideoCaptureFormat frame_format(
481 reserved_frame->coded_size().width(),
482 reserved_frame->coded_size().height(),
483 frame_rate,
484 media::VariableResolutionVideoCaptureDevice);
485
584 int count = 0; 486 int count = 0;
585 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 487 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
586 for (ControllerClients::iterator client_it = controller_clients_.begin(); 488 for (ControllerClients::iterator client_it = controller_clients_.begin();
587 client_it != controller_clients_.end(); ++client_it) { 489 client_it != controller_clients_.end(); ++client_it) {
588 if ((*client_it)->session_closed) 490 ControllerClient* client = *client_it;
491 if (client->session_closed)
589 continue; 492 continue;
590 493
591 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, 494 bool is_new_buffer = client->known_buffers.insert(buffer_id).second;
592 buffer_id, timestamp); 495 if (is_new_buffer) {
593 (*client_it)->buffers.insert(buffer_id); 496 // On the first use of a buffer on a client, share the memory handle.
497 size_t memory_size = 0;
498 base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess(
499 buffer_id, client->render_process_handle, &memory_size);
500 client->event_handler->OnBufferCreated(client->controller_id,
501 remote_handle,
502 memory_size,
503 buffer_id);
504 }
505
506 client->event_handler->OnBufferReady(client->controller_id,
507 buffer_id, timestamp,
508 frame_format);
509 bool inserted = client->active_buffers.insert(buffer_id).second;
510 DCHECK(inserted) << "Unexpected duplicate buffer: " << buffer_id;
594 count++; 511 count++;
595 } 512 }
596 } 513 }
597 514
598 buffer_pool_->HoldForConsumers(buffer_id, count); 515 buffer_pool_->HoldForConsumers(buffer_id, count);
599 } 516 }
600 517
601 void VideoCaptureController::DoFrameInfoOnIOThread(
602 const media::VideoCaptureCapability& frame_info,
603 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool) {
604 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
605 DCHECK(!buffer_pool_.get()) << "Frame info should happen only once.";
606
607 // Allocate memory only when device has been started.
608 if (state_ != VIDEO_CAPTURE_STATE_STARTED)
609 return;
610
611 frame_info_ = frame_info;
612 buffer_pool_ = buffer_pool;
613
614 for (ControllerClients::iterator client_it = controller_clients_.begin();
615 client_it != controller_clients_.end(); ++client_it) {
616 if ((*client_it)->session_closed)
617 continue;
618
619 SendFrameInfoAndBuffers(*client_it);
620 }
621 }
622
623 void VideoCaptureController::DoFrameInfoChangedOnIOThread(
624 const media::VideoCaptureCapability& info) {
625 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
626 // TODO(mcasas): Here we should reallocate the VideoCaptureBufferPool, if
627 // needed, to support the new video capture format. See crbug.com/266082.
628 for (ControllerClients::iterator client_it = controller_clients_.begin();
629 client_it != controller_clients_.end(); ++client_it) {
630 if ((*client_it)->session_closed)
631 continue;
632
633 (*client_it)->event_handler->OnFrameInfoChanged(
634 (*client_it)->controller_id,
635 info.width,
636 info.height,
637 info.frame_rate);
638 }
639 }
640
641 void VideoCaptureController::DoErrorOnIOThread() { 518 void VideoCaptureController::DoErrorOnIOThread() {
642 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
643 state_ = VIDEO_CAPTURE_STATE_ERROR; 520 state_ = VIDEO_CAPTURE_STATE_ERROR;
644 ControllerClients::iterator client_it; 521
645 for (client_it = controller_clients_.begin(); 522 for (ControllerClients::iterator client_it = controller_clients_.begin();
646 client_it != controller_clients_.end(); ++client_it) { 523 client_it != controller_clients_.end(); ++client_it) {
647 if ((*client_it)->session_closed) 524 ControllerClient* client = *client_it;
648 continue; 525 if (client->session_closed)
526 continue;
649 527
650 (*client_it)->event_handler->OnError((*client_it)->controller_id); 528 client->event_handler->OnError(client->controller_id);
651 } 529 }
652 } 530 }
653 531
654 void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) { 532 void VideoCaptureController::DoBufferDestroyedOnIOThread(
533 int buffer_id_to_drop) {
655 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 534 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
656 DCHECK(frame_info_.IsValid());
657 client->event_handler->OnFrameInfo(client->controller_id,
658 frame_info_);
659 for (int buffer_id = 0; buffer_id < buffer_pool_->count(); ++buffer_id) {
660 base::SharedMemoryHandle remote_handle =
661 buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle);
662 535
663 client->event_handler->OnBufferCreated(client->controller_id, 536 for (ControllerClients::iterator client_it = controller_clients_.begin();
664 remote_handle, 537 client_it != controller_clients_.end(); ++client_it) {
665 buffer_pool_->GetMemorySize(), 538 ControllerClient* client = *client_it;
666 buffer_id); 539 if (client->session_closed)
540 continue;
541
542 if (client->known_buffers.erase(buffer_id_to_drop)) {
543 client->event_handler->OnBufferDestroyed(client->controller_id,
544 buffer_id_to_drop);
545 }
667 } 546 }
668 } 547 }
669 548
670 VideoCaptureController::ControllerClient* 549 VideoCaptureController::ControllerClient*
671 VideoCaptureController::FindClient( 550 VideoCaptureController::FindClient(
672 const VideoCaptureControllerID& id, 551 const VideoCaptureControllerID& id,
673 VideoCaptureControllerEventHandler* handler, 552 VideoCaptureControllerEventHandler* handler,
674 const ControllerClients& clients) { 553 const ControllerClients& clients) {
675 for (ControllerClients::const_iterator client_it = clients.begin(); 554 for (ControllerClients::const_iterator client_it = clients.begin();
676 client_it != clients.end(); ++client_it) { 555 client_it != clients.end(); ++client_it) {
(...skipping 17 matching lines...) Expand all
694 } 573 }
695 return NULL; 574 return NULL;
696 } 575 }
697 576
698 int VideoCaptureController::GetClientCount() { 577 int VideoCaptureController::GetClientCount() {
699 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
700 return controller_clients_.size(); 579 return controller_clients_.size();
701 } 580 }
702 581
703 } // namespace content 582 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698