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

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: Fix constant declaration issue. 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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 ~ControllerClient() {} 70 ~ControllerClient() {}
71 71
72 // ID used for identifying this object. 72 // ID used for identifying this object.
73 VideoCaptureControllerID controller_id; 73 VideoCaptureControllerID controller_id;
74 VideoCaptureControllerEventHandler* event_handler; 74 VideoCaptureControllerEventHandler* event_handler;
75 75
76 // Handle to the render process that will receive the capture buffers. 76 // Handle to the render process that will receive the capture buffers.
77 base::ProcessHandle render_process_handle; 77 base::ProcessHandle render_process_handle;
78 media::VideoCaptureParams parameters; 78 media::VideoCaptureParams parameters;
79 79
80 // Buffers used by this client. 80 // Buffers that are currently known to this client.
81 std::set<int> buffers; 81 std::set<int> known_buffers;
82
83 // Buffers currently held by this client.
84 std::set<int> active_buffers;
82 85
83 // State of capture session, controlled by VideoCaptureManager directly. This 86 // State of capture session, controlled by VideoCaptureManager directly. This
84 // transitions to true as soon as StopSession() occurs, at which point the 87 // transitions to true as soon as StopSession() occurs, at which point the
85 // client is sent an OnEnded() event. However, because the client retains a 88 // client is sent an OnEnded() event. However, because the client retains a
86 // VideoCaptureController* pointer, its ControllerClient entry lives on until 89 // VideoCaptureController* pointer, its ControllerClient entry lives on until
87 // it unregisters itself via RemoveClient(), which may happen asynchronously. 90 // it unregisters itself via RemoveClient(), which may happen asynchronously.
88 // 91 //
89 // TODO(nick): If we changed the semantics of VideoCaptureHost so that 92 // TODO(nick): If we changed the semantics of VideoCaptureHost so that
90 // OnEnded() events were processed synchronously (with the RemoveClient() done 93 // OnEnded() events were processed synchronously (with the RemoveClient() done
91 // implicitly), we could avoid tracking this state here in the Controller, and 94 // implicitly), we could avoid tracking this state here in the Controller, and
92 // simplify the code in both places. 95 // simplify the code in both places.
93 bool session_closed; 96 bool session_closed;
94 }; 97 };
95 98
96 // Receives events from the VideoCaptureDevice and posts them to a 99 // Receives events from the VideoCaptureDevice and posts them to a
97 // VideoCaptureController on the IO thread. An instance of this class may safely 100 // VideoCaptureController on the IO thread. An instance of this class may safely
98 // outlive its target VideoCaptureController. 101 // outlive its target VideoCaptureController.
99 // 102 //
100 // Methods of this class may be called from any thread, and in practice will 103 // Methods of this class may be called from any thread, and in practice will
101 // often be called on some auxiliary thread depending on the platform and the 104 // often be called on some auxiliary thread depending on the platform and the
102 // device type; including, for example, the DirectShow thread on Windows, the 105 // device type; including, for example, the DirectShow thread on Windows, the
103 // v4l2_thread on Linux, and the UI thread for tab capture. 106 // v4l2_thread on Linux, and the UI thread for tab capture.
104 class VideoCaptureController::VideoCaptureDeviceClient 107 class VideoCaptureController::VideoCaptureDeviceClient
105 : public media::VideoCaptureDevice::Client { 108 : public media::VideoCaptureDevice::Client {
106 public: 109 public:
107 explicit VideoCaptureDeviceClient( 110 explicit VideoCaptureDeviceClient(
108 const base::WeakPtr<VideoCaptureController>& controller); 111 const base::WeakPtr<VideoCaptureController>& controller,
112 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool);
109 virtual ~VideoCaptureDeviceClient(); 113 virtual ~VideoCaptureDeviceClient();
110 114
111 // VideoCaptureDevice::Client implementation. 115 // VideoCaptureDevice::Client implementation.
112 virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE; 116 virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer(
117 const gfx::Size& size) OVERRIDE;
113 virtual void OnIncomingCapturedFrame(const uint8* data, 118 virtual void OnIncomingCapturedFrame(const uint8* data,
114 int length, 119 int length,
115 base::Time timestamp, 120 base::Time timestamp,
116 int rotation, 121 int rotation,
117 bool flip_vert, 122 bool flip_vert,
118 bool flip_horiz) OVERRIDE; 123 bool flip_horiz) OVERRIDE;
119 virtual void OnIncomingCapturedVideoFrame( 124 virtual void OnIncomingCapturedVideoFrame(
120 const scoped_refptr<media::VideoFrame>& frame, 125 const scoped_refptr<media::VideoFrame>& frame,
121 base::Time timestamp) OVERRIDE; 126 base::Time timestamp) OVERRIDE;
122 virtual void OnError() OVERRIDE; 127 virtual void OnError() OVERRIDE;
123 virtual void OnFrameInfo( 128 virtual void OnFrameInfo(
124 const media::VideoCaptureCapability& info) OVERRIDE; 129 const media::VideoCaptureCapability& info) OVERRIDE;
125 virtual void OnFrameInfoChanged( 130 virtual void OnFrameInfoChanged(
126 const media::VideoCaptureCapability& info) OVERRIDE; 131 const media::VideoCaptureCapability& info) OVERRIDE;
127 132
128 private: 133 private:
134 void HandleDroppedBufferId(int buffer_id_to_drop);
135
129 // The controller to which we post events. 136 // The controller to which we post events.
130 const base::WeakPtr<VideoCaptureController> controller_; 137 const base::WeakPtr<VideoCaptureController> controller_;
131 138
132 // The pool of shared-memory buffers used for capturing. 139 // The pool of shared-memory buffers used for capturing.
133 scoped_refptr<VideoCaptureBufferPool> buffer_pool_; 140 const scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
134 141
135 // Chopped pixels in width/height in case video capture device has odd 142 // Chopped pixels in width/height in case video capture device has odd
136 // numbers for width/height. 143 // numbers for width/height.
137 int chopped_width_; 144 int chopped_width_;
138 int chopped_height_; 145 int chopped_height_;
139 146
140 // Tracks the current frame format. 147 // Tracks the current frame format.
141 media::VideoCaptureCapability frame_info_; 148 media::VideoCaptureCapability frame_info_;
142 149
143 // For NV21 we have to do color conversion into the intermediate buffer and 150 // For NV21 we have to do color conversion into the intermediate buffer and
144 // from there the rotations. This variable won't be needed after 151 // from there the rotations. This variable won't be needed after
145 // http://crbug.com/292400 152 // http://crbug.com/292400
146 #if defined(OS_IOS) || defined(OS_ANDROID) 153 #if defined(OS_IOS) || defined(OS_ANDROID)
147 scoped_ptr<uint8[]> i420_intermediate_buffer_; 154 scoped_ptr<uint8[]> i420_intermediate_buffer_;
148 #endif // #if defined(OS_IOS) || defined(OS_ANDROID) 155 #endif // #if defined(OS_IOS) || defined(OS_ANDROID)
149 }; 156 };
150 157
151 VideoCaptureController::VideoCaptureController() 158 VideoCaptureController::VideoCaptureController()
152 : state_(VIDEO_CAPTURE_STATE_STARTED), 159 : buffer_pool_(new VideoCaptureBufferPool(kNoOfBuffers)),
160 state_(VIDEO_CAPTURE_STATE_STARTED),
153 weak_ptr_factory_(this) { 161 weak_ptr_factory_(this) {
154 memset(&current_params_, 0, sizeof(current_params_));
155 } 162 }
156 163
157 VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient( 164 VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient(
158 const base::WeakPtr<VideoCaptureController>& controller) 165 const base::WeakPtr<VideoCaptureController>& controller,
166 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool)
159 : controller_(controller), 167 : controller_(controller),
168 buffer_pool_(buffer_pool),
160 chopped_width_(0), 169 chopped_width_(0),
161 chopped_height_(0) {} 170 chopped_height_(0) {}
162 171
163 VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {} 172 VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {}
164 173
165 base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() { 174 base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() {
166 return weak_ptr_factory_.GetWeakPtr(); 175 return weak_ptr_factory_.GetWeakPtr();
167 } 176 }
168 177
169 scoped_ptr<media::VideoCaptureDevice::Client> 178 scoped_ptr<media::VideoCaptureDevice::Client>
170 VideoCaptureController::NewDeviceClient() { 179 VideoCaptureController::NewDeviceClient() {
171 scoped_ptr<media::VideoCaptureDevice::Client> result( 180 scoped_ptr<media::VideoCaptureDevice::Client> result(
172 new VideoCaptureDeviceClient(this->GetWeakPtr())); 181 new VideoCaptureDeviceClient(this->GetWeakPtr(), buffer_pool_));
173 return result.Pass(); 182 return result.Pass();
174 } 183 }
175 184
176 void VideoCaptureController::AddClient( 185 void VideoCaptureController::AddClient(
177 const VideoCaptureControllerID& id, 186 const VideoCaptureControllerID& id,
178 VideoCaptureControllerEventHandler* event_handler, 187 VideoCaptureControllerEventHandler* event_handler,
179 base::ProcessHandle render_process, 188 base::ProcessHandle render_process,
180 const media::VideoCaptureParams& params) { 189 const media::VideoCaptureParams& params) {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
182 DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id 191 DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id
(...skipping 11 matching lines...) Expand all
194 203
195 // Do nothing if this client has called AddClient before. 204 // Do nothing if this client has called AddClient before.
196 if (FindClient(id, event_handler, controller_clients_)) 205 if (FindClient(id, event_handler, controller_clients_))
197 return; 206 return;
198 207
199 ControllerClient* client = new ControllerClient(id, event_handler, 208 ControllerClient* client = new ControllerClient(id, event_handler,
200 render_process, params); 209 render_process, params);
201 // If we already have gotten frame_info from the device, repeat it to the new 210 // If we already have gotten frame_info from the device, repeat it to the new
202 // client. 211 // client.
203 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 212 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
204 if (frame_info_.IsValid()) {
205 SendFrameInfoAndBuffers(client);
206 }
207 controller_clients_.push_back(client); 213 controller_clients_.push_back(client);
208 return; 214 return;
209 } 215 }
210 } 216 }
211 217
212 int VideoCaptureController::RemoveClient( 218 int VideoCaptureController::RemoveClient(
213 const VideoCaptureControllerID& id, 219 const VideoCaptureControllerID& id,
214 VideoCaptureControllerEventHandler* event_handler) { 220 VideoCaptureControllerEventHandler* event_handler) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
216 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id; 222 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id;
217 223
218 ControllerClient* client = FindClient(id, event_handler, controller_clients_); 224 ControllerClient* client = FindClient(id, event_handler, controller_clients_);
219 if (!client) 225 if (!client)
220 return kInvalidMediaCaptureSessionId; 226 return kInvalidMediaCaptureSessionId;
221 227
222 // Take back all buffers held by the |client|. 228 // Take back all buffers held by the |client|.
223 if (buffer_pool_.get()) { 229 for (std::set<int>::iterator buffer_it = client->active_buffers.begin();
224 for (std::set<int>::iterator buffer_it = client->buffers.begin(); 230 buffer_it != client->active_buffers.end();
225 buffer_it != client->buffers.end(); 231 ++buffer_it) {
226 ++buffer_it) { 232 int buffer_id = *buffer_it;
227 int buffer_id = *buffer_it; 233 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
228 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
229 }
230 } 234 }
231 client->buffers.clear(); 235 client->active_buffers.clear();
232 236
233 int session_id = client->parameters.session_id; 237 int session_id = client->parameters.session_id;
234 controller_clients_.remove(client); 238 controller_clients_.remove(client);
235 delete client; 239 delete client;
236 240
237 return session_id; 241 return session_id;
238 } 242 }
239 243
240 void VideoCaptureController::StopSession(int session_id) { 244 void VideoCaptureController::StopSession(int session_id) {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 245 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
(...skipping 11 matching lines...) Expand all
253 const VideoCaptureControllerID& id, 257 const VideoCaptureControllerID& id,
254 VideoCaptureControllerEventHandler* event_handler, 258 VideoCaptureControllerEventHandler* event_handler,
255 int buffer_id) { 259 int buffer_id) {
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
257 261
258 ControllerClient* client = FindClient(id, event_handler, controller_clients_); 262 ControllerClient* client = FindClient(id, event_handler, controller_clients_);
259 263
260 // If this buffer is not held by this client, or this client doesn't exist 264 // If this buffer is not held by this client, or this client doesn't exist
261 // in controller, do nothing. 265 // in controller, do nothing.
262 if (!client || 266 if (!client ||
263 client->buffers.find(buffer_id) == client->buffers.end()) { 267 client->active_buffers.find(buffer_id) == client->active_buffers.end()) {
264 NOTREACHED(); 268 NOTREACHED();
265 return; 269 return;
266 } 270 }
267 271
268 client->buffers.erase(buffer_id); 272 client->active_buffers.erase(buffer_id);
269 buffer_pool_->RelinquishConsumerHold(buffer_id, 1); 273 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
270 } 274 }
271 275
272 scoped_refptr<media::VideoFrame> 276 scoped_refptr<media::VideoFrame>
273 VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer() { 277 VideoCaptureController::VideoCaptureDeviceClient::ReserveOutputBuffer(
274 return buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width, 278 const gfx::Size& size) {
275 frame_info_.height), 279 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
276 0); 280 scoped_refptr<media::VideoFrame> frame =
281 buffer_pool_->ReserveI420VideoFrame(size, 0, &buffer_id_to_drop);
282 HandleDroppedBufferId(buffer_id_to_drop);
283 return frame;
277 } 284 }
278 285
279 #if !defined(OS_IOS) && !defined(OS_ANDROID) 286 #if !defined(OS_IOS) && !defined(OS_ANDROID)
280 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( 287 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
281 const uint8* data, 288 const uint8* data,
282 int length, 289 int length,
283 base::Time timestamp, 290 base::Time timestamp,
284 int rotation, 291 int rotation,
285 bool flip_vert, 292 bool flip_vert,
286 bool flip_horiz) { 293 bool flip_horiz) {
287 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); 294 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
288 295
289 if (!buffer_pool_.get()) 296 if (!frame_info_.IsValid())
290 return; 297 return;
298
299 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
291 scoped_refptr<media::VideoFrame> dst = buffer_pool_->ReserveI420VideoFrame( 300 scoped_refptr<media::VideoFrame> dst = buffer_pool_->ReserveI420VideoFrame(
292 gfx::Size(frame_info_.width, frame_info_.height), rotation); 301 gfx::Size(frame_info_.width, frame_info_.height), rotation,
302 &buffer_id_to_drop);
303 HandleDroppedBufferId(buffer_id_to_drop);
293 304
294 if (!dst.get()) 305 if (!dst.get())
295 return; 306 return;
296 307
297 uint8* yplane = dst->data(media::VideoFrame::kYPlane); 308 uint8* yplane = dst->data(media::VideoFrame::kYPlane);
298 uint8* uplane = dst->data(media::VideoFrame::kUPlane); 309 uint8* uplane = dst->data(media::VideoFrame::kUPlane);
299 uint8* vplane = dst->data(media::VideoFrame::kVPlane); 310 uint8* vplane = dst->data(media::VideoFrame::kVPlane);
300 int yplane_stride = frame_info_.width; 311 int yplane_stride = frame_info_.width;
301 int uv_plane_stride = (frame_info_.width + 1) / 2; 312 int uv_plane_stride = (frame_info_.width + 1) / 2;
302 int crop_x = 0; 313 int crop_x = 0;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 frame_info_.height, 404 frame_info_.height,
394 rotation_mode, 405 rotation_mode,
395 origin_colorspace); 406 origin_colorspace);
396 } 407 }
397 BrowserThread::PostTask( 408 BrowserThread::PostTask(
398 BrowserThread::IO, 409 BrowserThread::IO,
399 FROM_HERE, 410 FROM_HERE,
400 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 411 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
401 controller_, 412 controller_,
402 dst, 413 dst,
414 frame_info_.frame_rate,
403 timestamp)); 415 timestamp));
404 } 416 }
405 #else 417 #else
406 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( 418 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
407 const uint8* data, 419 const uint8* data,
408 int length, 420 int length,
409 base::Time timestamp, 421 base::Time timestamp,
410 int rotation, 422 int rotation,
411 bool flip_vert, 423 bool flip_vert,
412 bool flip_horiz) { 424 bool flip_horiz) {
425
426 if (!frame_info_.IsValid())
427 return;
428
413 DCHECK(frame_info_.color == media::PIXEL_FORMAT_I420 || 429 DCHECK(frame_info_.color == media::PIXEL_FORMAT_I420 ||
414 frame_info_.color == media::PIXEL_FORMAT_YV12 || 430 frame_info_.color == media::PIXEL_FORMAT_YV12 ||
415 frame_info_.color == media::PIXEL_FORMAT_NV21 || 431 frame_info_.color == media::PIXEL_FORMAT_NV21 ||
416 (rotation == 0 && !flip_vert && !flip_horiz)); 432 (rotation == 0 && !flip_vert && !flip_horiz));
417 433
418 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); 434 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
419 435
420 if (!buffer_pool_) 436 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
421 return;
422 scoped_refptr<media::VideoFrame> dst = 437 scoped_refptr<media::VideoFrame> dst =
423 buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width, 438 buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
424 frame_info_.height), 439 frame_info_.height),
425 rotation); 440 rotation,
426 441 &buffer_id_to_drop);
442 HandleDroppedBufferId(buffer_id_to_drop);
427 if (!dst.get()) 443 if (!dst.get())
428 return; 444 return;
429 445
430 uint8* yplane = dst->data(media::VideoFrame::kYPlane); 446 uint8* yplane = dst->data(media::VideoFrame::kYPlane);
431 uint8* uplane = dst->data(media::VideoFrame::kUPlane); 447 uint8* uplane = dst->data(media::VideoFrame::kUPlane);
432 uint8* vplane = dst->data(media::VideoFrame::kVPlane); 448 uint8* vplane = dst->data(media::VideoFrame::kVPlane);
433 449
434 // Do color conversion from the camera format to I420. 450 // Do color conversion from the camera format to I420.
435 switch (frame_info_.color) { 451 switch (frame_info_.color) {
436 case media::PIXEL_FORMAT_UNKNOWN: // Color format not set. 452 case media::PIXEL_FORMAT_UNKNOWN: // Color format not set.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 (frame_info_.width + chopped_width_) * 4, 505 (frame_info_.width + chopped_width_) * 4,
490 frame_info_.width, frame_info_.width / 2); 506 frame_info_.width, frame_info_.width / 2);
491 break; 507 break;
492 default: 508 default:
493 NOTREACHED(); 509 NOTREACHED();
494 } 510 }
495 511
496 BrowserThread::PostTask(BrowserThread::IO, 512 BrowserThread::PostTask(BrowserThread::IO,
497 FROM_HERE, 513 FROM_HERE,
498 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 514 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
499 controller_, dst, timestamp)); 515 controller_, dst, frame_info_.frame_rate, timestamp));
500 } 516 }
501 #endif // #if !defined(OS_IOS) && !defined(OS_ANDROID) 517 #endif // #if !defined(OS_IOS) && !defined(OS_ANDROID)
502 518
503 void 519 void
504 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( 520 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
505 const scoped_refptr<media::VideoFrame>& frame, 521 const scoped_refptr<media::VideoFrame>& frame,
506 base::Time timestamp) { 522 base::Time timestamp) {
507 if (!buffer_pool_)
508 return;
509 523
510 // If this is a frame that belongs to the buffer pool, we can forward it 524 // If this is a frame that belongs to the buffer pool, we can forward it
511 // directly to the IO thread and be done. 525 // directly to the IO thread and be done.
512 if (buffer_pool_->RecognizeReservedBuffer( 526 if (buffer_pool_->RecognizeReservedBuffer(
513 frame->shared_memory_handle()) >= 0) { 527 frame->shared_memory_handle()) >= 0) {
514 BrowserThread::PostTask(BrowserThread::IO, 528 BrowserThread::PostTask(BrowserThread::IO,
515 FROM_HERE, 529 FROM_HERE,
516 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 530 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
517 controller_, frame, timestamp)); 531 controller_, frame, frame_info_.frame_rate, timestamp));
518 return; 532 return;
519 } 533 }
520 534
521 // Otherwise, this is a frame that belongs to the caller, and we must copy 535 NOTREACHED() << "Frames should always belong to the buffer pool.";
522 // it to a frame from the buffer pool.
523 scoped_refptr<media::VideoFrame> target =
524 buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
525 frame_info_.height),
526 0);
527
528 if (!target.get())
529 return;
530
531 // Validate the inputs.
532 if (frame->coded_size() != target->coded_size())
533 return; // Only exact copies are supported.
534 if (!(frame->format() == media::VideoFrame::I420 ||
535 frame->format() == media::VideoFrame::YV12 ||
536 frame->format() == media::VideoFrame::RGB32)) {
537 NOTREACHED() << "Unsupported format passed to OnIncomingCapturedVideoFrame";
538 return;
539 }
540
541 const int kYPlane = media::VideoFrame::kYPlane;
542 const int kUPlane = media::VideoFrame::kUPlane;
543 const int kVPlane = media::VideoFrame::kVPlane;
544 const int kAPlane = media::VideoFrame::kAPlane;
545 const int kRGBPlane = media::VideoFrame::kRGBPlane;
546
547 // Do color conversion from the camera format to I420.
548 switch (frame->format()) {
549 #if defined(GOOGLE_TV)
550 case media::VideoFrame::HOLE:
551 // Fall-through to NOTREACHED() block.
552 #endif
553 case media::VideoFrame::INVALID:
554 case media::VideoFrame::YV16:
555 case media::VideoFrame::EMPTY:
556 case media::VideoFrame::NATIVE_TEXTURE: {
557 NOTREACHED();
558 break;
559 }
560 case media::VideoFrame::I420:
561 case media::VideoFrame::YV12: {
562 DCHECK(!chopped_width_ && !chopped_height_);
563 media::CopyYPlane(frame->data(kYPlane),
564 frame->stride(kYPlane),
565 frame->rows(kYPlane),
566 target.get());
567 media::CopyUPlane(frame->data(kUPlane),
568 frame->stride(kUPlane),
569 frame->rows(kUPlane),
570 target.get());
571 media::CopyVPlane(frame->data(kVPlane),
572 frame->stride(kVPlane),
573 frame->rows(kVPlane),
574 target.get());
575 break;
576 }
577 case media::VideoFrame::YV12A: {
578 DCHECK(!chopped_width_ && !chopped_height_);
579 media::CopyYPlane(frame->data(kYPlane),
580 frame->stride(kYPlane),
581 frame->rows(kYPlane),
582 target.get());
583 media::CopyUPlane(frame->data(kUPlane),
584 frame->stride(kUPlane),
585 frame->rows(kUPlane),
586 target.get());
587 media::CopyVPlane(frame->data(kVPlane),
588 frame->stride(kVPlane),
589 frame->rows(kVPlane),
590 target.get());
591 media::CopyAPlane(frame->data(kAPlane),
592 frame->stride(kAPlane),
593 frame->rows(kAPlane),
594 target.get());
595 break;
596 }
597 case media::VideoFrame::RGB32: {
598 media::ConvertRGB32ToYUV(frame->data(kRGBPlane),
599 target->data(kYPlane),
600 target->data(kUPlane),
601 target->data(kVPlane),
602 target->coded_size().width(),
603 target->coded_size().height(),
604 frame->stride(kRGBPlane),
605 target->stride(kYPlane),
606 target->stride(kUPlane));
607 break;
608 }
609 }
610
611 BrowserThread::PostTask(BrowserThread::IO,
612 FROM_HERE,
613 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
614 controller_, target, timestamp));
615 } 536 }
616 537
617 void VideoCaptureController::VideoCaptureDeviceClient::OnError() { 538 void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
618 BrowserThread::PostTask(BrowserThread::IO, 539 BrowserThread::PostTask(BrowserThread::IO,
619 FROM_HERE, 540 FROM_HERE,
620 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); 541 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
621 } 542 }
622 543
623 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo( 544 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo(
624 const media::VideoCaptureCapability& info) { 545 const media::VideoCaptureCapability& info) {
625 frame_info_ = info; 546 frame_info_ = info;
626 // Handle cases when |info| has odd numbers for width/height. 547 // Handle cases when |info| has odd numbers for width/height.
627 if (info.width & 1) { 548 if (info.width & 1) {
628 --frame_info_.width; 549 --frame_info_.width;
629 chopped_width_ = 1; 550 chopped_width_ = 1;
630 } else { 551 } else {
631 chopped_width_ = 0; 552 chopped_width_ = 0;
632 } 553 }
633 if (info.height & 1) { 554 if (info.height & 1) {
634 --frame_info_.height; 555 --frame_info_.height;
635 chopped_height_ = 1; 556 chopped_height_ = 1;
636 } else { 557 } else {
637 chopped_height_ = 0; 558 chopped_height_ = 0;
638 } 559 }
639 #if defined(OS_IOS) || defined(OS_ANDROID) 560 #if defined(OS_IOS) || defined(OS_ANDROID)
640 if (frame_info_.color == media::PIXEL_FORMAT_NV21 && 561 if (frame_info_.color == media::PIXEL_FORMAT_NV21) {
641 !i420_intermediate_buffer_) {
642 i420_intermediate_buffer_.reset( 562 i420_intermediate_buffer_.reset(
643 new uint8[frame_info_.width * frame_info_.height * 12 / 8]); 563 new uint8[frame_info_.width * frame_info_.height * 12 / 8]);
644 } 564 }
645 #endif // #if defined(OS_IOS) || defined(OS_ANDROID) 565 #endif // #if defined(OS_IOS) || defined(OS_ANDROID)
646
647 DCHECK(!buffer_pool_.get());
648
649 // TODO(nick): Give BufferPool the same lifetime as the controller, have it
650 // support frame size changes, and stop checking it for NULL everywhere.
651 // http://crbug.com/266082
652 buffer_pool_ = new VideoCaptureBufferPool(
653 media::VideoFrame::AllocationSize(
654 media::VideoFrame::I420,
655 gfx::Size(frame_info_.width, frame_info_.height)),
656 kNoOfBuffers);
657
658 // Check whether all buffers were created successfully.
659 if (!buffer_pool_->Allocate()) {
660 // Transition to the error state.
661 buffer_pool_ = NULL;
662 OnError();
663 return;
664 }
665
666 BrowserThread::PostTask(BrowserThread::IO,
667 FROM_HERE,
668 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, controller_,
669 frame_info_, buffer_pool_));
670 } 566 }
671 567
672 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged( 568 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged(
673 const media::VideoCaptureCapability& info) { 569 const media::VideoCaptureCapability& info) {
674 BrowserThread::PostTask(BrowserThread::IO, 570 OnFrameInfo(info);
675 FROM_HERE, 571 }
676 base::Bind(&VideoCaptureController::DoFrameInfoChangedOnIOThread, 572
677 controller_, info)); 573 void VideoCaptureController::VideoCaptureDeviceClient::HandleDroppedBufferId(
574 int buffer_id_to_drop) {
575 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) {
576 BrowserThread::PostTask(BrowserThread::IO,
577 FROM_HERE,
578 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread,
579 controller_, buffer_id_to_drop));
580 }
678 } 581 }
679 582
680 VideoCaptureController::~VideoCaptureController() { 583 VideoCaptureController::~VideoCaptureController() {
681 buffer_pool_ = NULL; // Release all buffers.
682 STLDeleteContainerPointers(controller_clients_.begin(), 584 STLDeleteContainerPointers(controller_clients_.begin(),
683 controller_clients_.end()); 585 controller_clients_.end());
684 } 586 }
685 587
686 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( 588 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
687 const scoped_refptr<media::VideoFrame>& reserved_frame, 589 const scoped_refptr<media::VideoFrame>& reserved_frame,
590 int frame_rate,
688 base::Time timestamp) { 591 base::Time timestamp) {
689 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 592 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
690 593
691 if (!buffer_pool_.get())
692 return;
693
694 int buffer_id = buffer_pool_->RecognizeReservedBuffer( 594 int buffer_id = buffer_pool_->RecognizeReservedBuffer(
695 reserved_frame->shared_memory_handle()); 595 reserved_frame->shared_memory_handle());
696 if (buffer_id < 0) { 596 if (buffer_id < 0) {
697 NOTREACHED(); 597 NOTREACHED();
698 return; 598 return;
699 } 599 }
700 600
601 media::VideoCaptureFormat frame_format(
602 reserved_frame->coded_size().width(),
603 reserved_frame->coded_size().height(),
604 frame_rate,
605 media::VariableResolutionVideoCaptureDevice);
606
701 int count = 0; 607 int count = 0;
702 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 608 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
703 for (ControllerClients::iterator client_it = controller_clients_.begin(); 609 for (ControllerClients::iterator client_it = controller_clients_.begin();
704 client_it != controller_clients_.end(); ++client_it) { 610 client_it != controller_clients_.end(); ++client_it) {
705 if ((*client_it)->session_closed) 611 ControllerClient* client = *client_it;
612 if (client->session_closed)
706 continue; 613 continue;
707 614
708 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, 615 if (!client->known_buffers.count(buffer_id)) {
709 buffer_id, timestamp); 616 // On the first use of a buffer on a client, share the memory handle.
710 (*client_it)->buffers.insert(buffer_id); 617 size_t memory_size = 0;
618 base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess(
619 buffer_id, client->render_process_handle, &memory_size);
620 client->event_handler->OnBufferCreated(client->controller_id,
621 remote_handle,
622 memory_size,
623 buffer_id);
624 client->known_buffers.insert(buffer_id);
625 }
626
627 client->event_handler->OnBufferReady(client->controller_id,
628 buffer_id, timestamp,
629 frame_format);
630 client->active_buffers.insert(buffer_id);
711 count++; 631 count++;
712 } 632 }
713 } 633 }
714 634
715 buffer_pool_->HoldForConsumers(buffer_id, count); 635 buffer_pool_->HoldForConsumers(buffer_id, count);
716 } 636 }
717 637
718 void VideoCaptureController::DoFrameInfoOnIOThread(
719 const media::VideoCaptureCapability& frame_info,
720 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool) {
721 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
722 DCHECK(!buffer_pool_.get()) << "Frame info should happen only once.";
723
724 // Allocate memory only when device has been started.
725 if (state_ != VIDEO_CAPTURE_STATE_STARTED)
726 return;
727
728 frame_info_ = frame_info;
729 buffer_pool_ = buffer_pool;
730
731 for (ControllerClients::iterator client_it = controller_clients_.begin();
732 client_it != controller_clients_.end(); ++client_it) {
733 if ((*client_it)->session_closed)
734 continue;
735
736 SendFrameInfoAndBuffers(*client_it);
737 }
738 }
739
740 void VideoCaptureController::DoFrameInfoChangedOnIOThread(
741 const media::VideoCaptureCapability& info) {
742 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
743 // TODO(mcasas): Here we should reallocate the VideoCaptureBufferPool, if
744 // needed, to support the new video capture format. See crbug.com/266082.
745 for (ControllerClients::iterator client_it = controller_clients_.begin();
746 client_it != controller_clients_.end(); ++client_it) {
747 if ((*client_it)->session_closed)
748 continue;
749
750 (*client_it)->event_handler->OnFrameInfoChanged(
751 (*client_it)->controller_id,
752 info.width,
753 info.height,
754 info.frame_rate);
755 }
756 }
757
758 void VideoCaptureController::DoErrorOnIOThread() { 638 void VideoCaptureController::DoErrorOnIOThread() {
759 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 639 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
760 state_ = VIDEO_CAPTURE_STATE_ERROR; 640 state_ = VIDEO_CAPTURE_STATE_ERROR;
761 ControllerClients::iterator client_it; 641
762 for (client_it = controller_clients_.begin(); 642 for (ControllerClients::iterator client_it = controller_clients_.begin();
763 client_it != controller_clients_.end(); ++client_it) { 643 client_it != controller_clients_.end(); ++client_it) {
764 if ((*client_it)->session_closed) 644 ControllerClient* client = *client_it;
765 continue; 645 if (client->session_closed)
646 continue;
766 647
767 (*client_it)->event_handler->OnError((*client_it)->controller_id); 648 client->event_handler->OnError(client->controller_id);
768 } 649 }
769 } 650 }
770 651
771 void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) { 652 void VideoCaptureController::DoBufferDestroyedOnIOThread(
653 int buffer_id_to_drop) {
772 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 654 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
773 DCHECK(frame_info_.IsValid());
774 client->event_handler->OnFrameInfo(client->controller_id,
775 frame_info_);
776 for (int buffer_id = 0; buffer_id < buffer_pool_->count(); ++buffer_id) {
777 base::SharedMemoryHandle remote_handle =
778 buffer_pool_->ShareToProcess(buffer_id, client->render_process_handle);
779 655
780 client->event_handler->OnBufferCreated(client->controller_id, 656 for (ControllerClients::iterator client_it = controller_clients_.begin();
781 remote_handle, 657 client_it != controller_clients_.end(); ++client_it) {
782 buffer_pool_->GetMemorySize(), 658 ControllerClient* client = *client_it;
783 buffer_id); 659 if (client->session_closed)
660 continue;
661
662 if (client->known_buffers.erase(buffer_id_to_drop)) {
663 client->event_handler->OnBufferDestroyed(client->controller_id,
664 buffer_id_to_drop);
665 }
784 } 666 }
785 } 667 }
786 668
787 VideoCaptureController::ControllerClient* 669 VideoCaptureController::ControllerClient*
788 VideoCaptureController::FindClient( 670 VideoCaptureController::FindClient(
789 const VideoCaptureControllerID& id, 671 const VideoCaptureControllerID& id,
790 VideoCaptureControllerEventHandler* handler, 672 VideoCaptureControllerEventHandler* handler,
791 const ControllerClients& clients) { 673 const ControllerClients& clients) {
792 for (ControllerClients::const_iterator client_it = clients.begin(); 674 for (ControllerClients::const_iterator client_it = clients.begin();
793 client_it != clients.end(); ++client_it) { 675 client_it != clients.end(); ++client_it) {
(...skipping 17 matching lines...) Expand all
811 } 693 }
812 return NULL; 694 return NULL;
813 } 695 }
814 696
815 int VideoCaptureController::GetClientCount() { 697 int VideoCaptureController::GetClientCount() {
816 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 698 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
817 return controller_clients_.size(); 699 return controller_clients_.size();
818 } 700 }
819 701
820 } // namespace content 702 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698