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

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: Rework IPC serialization, VideoCaptureParams switch to composition, eliminate OnFrameInfo for PPAPI… 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 scoped_refptr<media::VideoFrame> DoReserveI420VideoFrame(
135 const gfx::Size& size,
136 int rotation);
137
129 // The controller to which we post events. 138 // The controller to which we post events.
130 const base::WeakPtr<VideoCaptureController> controller_; 139 const base::WeakPtr<VideoCaptureController> controller_;
131 140
132 // The pool of shared-memory buffers used for capturing. 141 // The pool of shared-memory buffers used for capturing.
133 scoped_refptr<VideoCaptureBufferPool> buffer_pool_; 142 const scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
134 143
135 // Chopped pixels in width/height in case video capture device has odd 144 // Chopped pixels in width/height in case video capture device has odd
136 // numbers for width/height. 145 // numbers for width/height.
137 int chopped_width_; 146 int chopped_width_;
138 int chopped_height_; 147 int chopped_height_;
139 148
140 // Tracks the current frame format. 149 // Tracks the current frame format.
141 media::VideoCaptureCapability frame_info_; 150 media::VideoCaptureCapability frame_info_;
142 151
143 // For NV21 we have to do color conversion into the intermediate buffer and 152 // 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 153 // from there the rotations. This variable won't be needed after
145 // http://crbug.com/292400 154 // http://crbug.com/292400
146 #if defined(OS_IOS) || defined(OS_ANDROID) 155 #if defined(OS_IOS) || defined(OS_ANDROID)
147 scoped_ptr<uint8[]> i420_intermediate_buffer_; 156 scoped_ptr<uint8[]> i420_intermediate_buffer_;
148 #endif // #if defined(OS_IOS) || defined(OS_ANDROID) 157 #endif // #if defined(OS_IOS) || defined(OS_ANDROID)
149 }; 158 };
150 159
151 VideoCaptureController::VideoCaptureController() 160 VideoCaptureController::VideoCaptureController()
152 : state_(VIDEO_CAPTURE_STATE_STARTED), 161 : buffer_pool_(new VideoCaptureBufferPool(kNoOfBuffers)),
162 state_(VIDEO_CAPTURE_STATE_STARTED),
153 weak_ptr_factory_(this) { 163 weak_ptr_factory_(this) {
154 memset(&current_params_, 0, sizeof(current_params_));
155 } 164 }
156 165
157 VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient( 166 VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient(
158 const base::WeakPtr<VideoCaptureController>& controller) 167 const base::WeakPtr<VideoCaptureController>& controller,
168 const scoped_refptr<VideoCaptureBufferPool>& buffer_pool)
159 : controller_(controller), 169 : controller_(controller),
170 buffer_pool_(buffer_pool),
160 chopped_width_(0), 171 chopped_width_(0),
161 chopped_height_(0) {} 172 chopped_height_(0) {}
162 173
163 VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {} 174 VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {}
164 175
165 base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() { 176 base::WeakPtr<VideoCaptureController> VideoCaptureController::GetWeakPtr() {
166 return weak_ptr_factory_.GetWeakPtr(); 177 return weak_ptr_factory_.GetWeakPtr();
167 } 178 }
168 179
169 scoped_ptr<media::VideoCaptureDevice::Client> 180 scoped_ptr<media::VideoCaptureDevice::Client>
170 VideoCaptureController::NewDeviceClient() { 181 VideoCaptureController::NewDeviceClient() {
171 scoped_ptr<media::VideoCaptureDevice::Client> result( 182 scoped_ptr<media::VideoCaptureDevice::Client> result(
172 new VideoCaptureDeviceClient(this->GetWeakPtr())); 183 new VideoCaptureDeviceClient(this->GetWeakPtr(), buffer_pool_));
173 return result.Pass(); 184 return result.Pass();
174 } 185 }
175 186
176 void VideoCaptureController::AddClient( 187 void VideoCaptureController::AddClient(
177 const VideoCaptureControllerID& id, 188 const VideoCaptureControllerID& id,
178 VideoCaptureControllerEventHandler* event_handler, 189 VideoCaptureControllerEventHandler* event_handler,
179 base::ProcessHandle render_process, 190 base::ProcessHandle render_process,
180 const media::VideoCaptureParams& params) { 191 const media::VideoCaptureParams& params) {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
182 DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id 193 DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id
183 << ", (" << params.width 194 << ", (" << params.requested_format.width
184 << ", " << params.height 195 << ", " << params.requested_format.height
185 << ", " << params.frame_rate 196 << ", " << params.requested_format.frame_rate
186 << ", " << params.session_id 197 << ", " << params.session_id
187 << ")"; 198 << ")";
188 199
189 // Signal error in case device is already in error state. 200 // Signal error in case device is already in error state.
190 if (state_ == VIDEO_CAPTURE_STATE_ERROR) { 201 if (state_ == VIDEO_CAPTURE_STATE_ERROR) {
191 event_handler->OnError(id); 202 event_handler->OnError(id);
192 return; 203 return;
193 } 204 }
194 205
195 // Do nothing if this client has called AddClient before. 206 // Do nothing if this client has called AddClient before.
196 if (FindClient(id, event_handler, controller_clients_)) 207 if (FindClient(id, event_handler, controller_clients_))
197 return; 208 return;
198 209
199 ControllerClient* client = new ControllerClient(id, event_handler, 210 ControllerClient* client = new ControllerClient(id, event_handler,
200 render_process, params); 211 render_process, params);
201 // If we already have gotten frame_info from the device, repeat it to the new 212 // If we already have gotten frame_info from the device, repeat it to the new
202 // client. 213 // client.
203 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 214 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
204 if (frame_info_.IsValid()) {
205 SendFrameInfoAndBuffers(client);
206 }
207 controller_clients_.push_back(client); 215 controller_clients_.push_back(client);
208 return; 216 return;
209 } 217 }
210 } 218 }
211 219
212 int VideoCaptureController::RemoveClient( 220 int VideoCaptureController::RemoveClient(
213 const VideoCaptureControllerID& id, 221 const VideoCaptureControllerID& id,
214 VideoCaptureControllerEventHandler* event_handler) { 222 VideoCaptureControllerEventHandler* event_handler) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
216 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id; 224 DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id;
217 225
218 ControllerClient* client = FindClient(id, event_handler, controller_clients_); 226 ControllerClient* client = FindClient(id, event_handler, controller_clients_);
219 if (!client) 227 if (!client)
220 return kInvalidMediaCaptureSessionId; 228 return kInvalidMediaCaptureSessionId;
221 229
222 // Take back all buffers held by the |client|. 230 // Take back all buffers held by the |client|.
223 if (buffer_pool_.get()) { 231 for (std::set<int>::iterator buffer_it = client->active_buffers.begin();
224 for (std::set<int>::iterator buffer_it = client->buffers.begin(); 232 buffer_it != client->active_buffers.end();
225 buffer_it != client->buffers.end(); 233 ++buffer_it) {
226 ++buffer_it) { 234 int buffer_id = *buffer_it;
227 int buffer_id = *buffer_it; 235 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
228 buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
229 }
230 } 236 }
231 client->buffers.clear(); 237 client->active_buffers.clear();
232 238
233 int session_id = client->parameters.session_id; 239 int session_id = client->parameters.session_id;
234 controller_clients_.remove(client); 240 controller_clients_.remove(client);
235 delete client; 241 delete client;
236 242
237 return session_id; 243 return session_id;
238 } 244 }
239 245
240 void VideoCaptureController::StopSession(int session_id) { 246 void VideoCaptureController::StopSession(int session_id) {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
(...skipping 10 matching lines...) Expand all
252 void VideoCaptureController::ReturnBuffer( 258 void VideoCaptureController::ReturnBuffer(
253 const VideoCaptureControllerID& id, 259 const VideoCaptureControllerID& id,
254 VideoCaptureControllerEventHandler* event_handler, 260 VideoCaptureControllerEventHandler* event_handler,
255 int buffer_id) { 261 int buffer_id) {
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
257 263
258 ControllerClient* client = FindClient(id, event_handler, controller_clients_); 264 ControllerClient* client = FindClient(id, event_handler, controller_clients_);
259 265
260 // If this buffer is not held by this client, or this client doesn't exist 266 // If this buffer is not held by this client, or this client doesn't exist
261 // in controller, do nothing. 267 // in controller, do nothing.
262 if (!client || 268 if (!client || !client->active_buffers.erase(buffer_id)) {
263 client->buffers.find(buffer_id) == client->buffers.end()) {
264 NOTREACHED(); 269 NOTREACHED();
265 return; 270 return;
266 } 271 }
267 272
268 client->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 return DoReserveI420VideoFrame(size, 0);
276 0);
277 } 280 }
278 281
279 #if !defined(OS_IOS) && !defined(OS_ANDROID) 282 #if !defined(OS_IOS) && !defined(OS_ANDROID)
280 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( 283 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
281 const uint8* data, 284 const uint8* data,
282 int length, 285 int length,
283 base::Time timestamp, 286 base::Time timestamp,
284 int rotation, 287 int rotation,
285 bool flip_vert, 288 bool flip_vert,
286 bool flip_horiz) { 289 bool flip_horiz) {
287 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); 290 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
288 291
289 if (!buffer_pool_.get()) 292 if (!frame_info_.IsValid())
290 return; 293 return;
291 scoped_refptr<media::VideoFrame> dst = buffer_pool_->ReserveI420VideoFrame( 294
295 scoped_refptr<media::VideoFrame> dst = DoReserveI420VideoFrame(
292 gfx::Size(frame_info_.width, frame_info_.height), rotation); 296 gfx::Size(frame_info_.width, frame_info_.height), rotation);
293 297
294 if (!dst.get()) 298 if (!dst.get())
295 return; 299 return;
296 300
297 uint8* yplane = dst->data(media::VideoFrame::kYPlane); 301 uint8* yplane = dst->data(media::VideoFrame::kYPlane);
298 uint8* uplane = dst->data(media::VideoFrame::kUPlane); 302 uint8* uplane = dst->data(media::VideoFrame::kUPlane);
299 uint8* vplane = dst->data(media::VideoFrame::kVPlane); 303 uint8* vplane = dst->data(media::VideoFrame::kVPlane);
300 int yplane_stride = frame_info_.width; 304 int yplane_stride = frame_info_.width;
301 int uv_plane_stride = (frame_info_.width + 1) / 2; 305 int uv_plane_stride = (frame_info_.width + 1) / 2;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 frame_info_.height, 397 frame_info_.height,
394 rotation_mode, 398 rotation_mode,
395 origin_colorspace); 399 origin_colorspace);
396 } 400 }
397 BrowserThread::PostTask( 401 BrowserThread::PostTask(
398 BrowserThread::IO, 402 BrowserThread::IO,
399 FROM_HERE, 403 FROM_HERE,
400 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 404 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
401 controller_, 405 controller_,
402 dst, 406 dst,
407 frame_info_.frame_rate,
403 timestamp)); 408 timestamp));
404 } 409 }
405 #else 410 #else
406 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame( 411 void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedFrame(
407 const uint8* data, 412 const uint8* data,
408 int length, 413 int length,
409 base::Time timestamp, 414 base::Time timestamp,
410 int rotation, 415 int rotation,
411 bool flip_vert, 416 bool flip_vert,
412 bool flip_horiz) { 417 bool flip_horiz) {
418
419 if (!frame_info_.IsValid())
420 return;
421
413 DCHECK(frame_info_.color == media::PIXEL_FORMAT_I420 || 422 DCHECK(frame_info_.color == media::PIXEL_FORMAT_I420 ||
414 frame_info_.color == media::PIXEL_FORMAT_YV12 || 423 frame_info_.color == media::PIXEL_FORMAT_YV12 ||
415 frame_info_.color == media::PIXEL_FORMAT_NV21 || 424 frame_info_.color == media::PIXEL_FORMAT_NV21 ||
416 (rotation == 0 && !flip_vert && !flip_horiz)); 425 (rotation == 0 && !flip_vert && !flip_horiz));
417 426
418 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame"); 427 TRACE_EVENT0("video", "VideoCaptureController::OnIncomingCapturedFrame");
419 428
420 if (!buffer_pool_) 429 scoped_refptr<media::VideoFrame> dst = DoReserveI420VideoFrame(
421 return; 430 gfx::Size(frame_info_.width, frame_info_.height), rotation);
422 scoped_refptr<media::VideoFrame> dst =
423 buffer_pool_->ReserveI420VideoFrame(gfx::Size(frame_info_.width,
424 frame_info_.height),
425 rotation);
426 431
427 if (!dst.get()) 432 if (!dst.get())
428 return; 433 return;
429 434
430 uint8* yplane = dst->data(media::VideoFrame::kYPlane); 435 uint8* yplane = dst->data(media::VideoFrame::kYPlane);
431 uint8* uplane = dst->data(media::VideoFrame::kUPlane); 436 uint8* uplane = dst->data(media::VideoFrame::kUPlane);
432 uint8* vplane = dst->data(media::VideoFrame::kVPlane); 437 uint8* vplane = dst->data(media::VideoFrame::kVPlane);
433 438
434 // Do color conversion from the camera format to I420. 439 // Do color conversion from the camera format to I420.
435 switch (frame_info_.color) { 440 switch (frame_info_.color) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 (frame_info_.width + chopped_width_) * 4, 494 (frame_info_.width + chopped_width_) * 4,
490 frame_info_.width, frame_info_.width / 2); 495 frame_info_.width, frame_info_.width / 2);
491 break; 496 break;
492 default: 497 default:
493 NOTREACHED(); 498 NOTREACHED();
494 } 499 }
495 500
496 BrowserThread::PostTask(BrowserThread::IO, 501 BrowserThread::PostTask(BrowserThread::IO,
497 FROM_HERE, 502 FROM_HERE,
498 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 503 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
499 controller_, dst, timestamp)); 504 controller_, dst, frame_info_.frame_rate, timestamp));
500 } 505 }
501 #endif // #if !defined(OS_IOS) && !defined(OS_ANDROID) 506 #endif // #if !defined(OS_IOS) && !defined(OS_ANDROID)
502 507
503 void 508 void
504 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame( 509 VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
505 const scoped_refptr<media::VideoFrame>& frame, 510 const scoped_refptr<media::VideoFrame>& frame,
506 base::Time timestamp) { 511 base::Time timestamp) {
507 if (!buffer_pool_)
508 return;
509 512
510 // If this is a frame that belongs to the buffer pool, we can forward it 513 // If this is a frame that belongs to the buffer pool, we can forward it
511 // directly to the IO thread and be done. 514 // directly to the IO thread and be done.
512 if (buffer_pool_->RecognizeReservedBuffer( 515 if (buffer_pool_->RecognizeReservedBuffer(
513 frame->shared_memory_handle()) >= 0) { 516 frame->shared_memory_handle()) >= 0) {
514 BrowserThread::PostTask(BrowserThread::IO, 517 BrowserThread::PostTask(BrowserThread::IO,
515 FROM_HERE, 518 FROM_HERE,
516 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, 519 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread,
517 controller_, frame, timestamp)); 520 controller_, frame, frame_info_.frame_rate, timestamp));
518 return; 521 return;
519 } 522 }
520 523
521 // Otherwise, this is a frame that belongs to the caller, and we must copy 524 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 } 525 }
616 526
617 void VideoCaptureController::VideoCaptureDeviceClient::OnError() { 527 void VideoCaptureController::VideoCaptureDeviceClient::OnError() {
618 BrowserThread::PostTask(BrowserThread::IO, 528 BrowserThread::PostTask(BrowserThread::IO,
619 FROM_HERE, 529 FROM_HERE,
620 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_)); 530 base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
621 } 531 }
622 532
623 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo( 533 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfo(
624 const media::VideoCaptureCapability& info) { 534 const media::VideoCaptureCapability& info) {
625 frame_info_ = info; 535 frame_info_ = info;
626 // Handle cases when |info| has odd numbers for width/height. 536 // Handle cases when |info| has odd numbers for width/height.
627 if (info.width & 1) { 537 if (info.width & 1) {
628 --frame_info_.width; 538 --frame_info_.width;
629 chopped_width_ = 1; 539 chopped_width_ = 1;
630 } else { 540 } else {
631 chopped_width_ = 0; 541 chopped_width_ = 0;
632 } 542 }
633 if (info.height & 1) { 543 if (info.height & 1) {
634 --frame_info_.height; 544 --frame_info_.height;
635 chopped_height_ = 1; 545 chopped_height_ = 1;
636 } else { 546 } else {
637 chopped_height_ = 0; 547 chopped_height_ = 0;
638 } 548 }
639 #if defined(OS_IOS) || defined(OS_ANDROID) 549 #if defined(OS_IOS) || defined(OS_ANDROID)
640 if (frame_info_.color == media::PIXEL_FORMAT_NV21 && 550 if (frame_info_.color == media::PIXEL_FORMAT_NV21) {
641 !i420_intermediate_buffer_) {
642 i420_intermediate_buffer_.reset( 551 i420_intermediate_buffer_.reset(
643 new uint8[frame_info_.width * frame_info_.height * 12 / 8]); 552 new uint8[frame_info_.width * frame_info_.height * 12 / 8]);
644 } 553 }
645 #endif // #if defined(OS_IOS) || defined(OS_ANDROID) 554 #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 } 555 }
671 556
672 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged( 557 void VideoCaptureController::VideoCaptureDeviceClient::OnFrameInfoChanged(
673 const media::VideoCaptureCapability& info) { 558 const media::VideoCaptureCapability& info) {
674 BrowserThread::PostTask(BrowserThread::IO, 559 OnFrameInfo(info);
675 FROM_HERE, 560 }
676 base::Bind(&VideoCaptureController::DoFrameInfoChangedOnIOThread, 561
677 controller_, info)); 562 scoped_refptr<media::VideoFrame>
563 VideoCaptureController::VideoCaptureDeviceClient::DoReserveI420VideoFrame(
564 const gfx::Size& size,
565 int rotation) {
566 int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
567 scoped_refptr<media::VideoFrame> frame =
568 buffer_pool_->ReserveI420VideoFrame(size, rotation, &buffer_id_to_drop);
569 if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) {
570 BrowserThread::PostTask(BrowserThread::IO,
571 FROM_HERE,
572 base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread,
573 controller_, buffer_id_to_drop));
574 }
575 return frame;
678 } 576 }
679 577
680 VideoCaptureController::~VideoCaptureController() { 578 VideoCaptureController::~VideoCaptureController() {
681 buffer_pool_ = NULL; // Release all buffers.
682 STLDeleteContainerPointers(controller_clients_.begin(), 579 STLDeleteContainerPointers(controller_clients_.begin(),
683 controller_clients_.end()); 580 controller_clients_.end());
684 } 581 }
685 582
686 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread( 583 void VideoCaptureController::DoIncomingCapturedFrameOnIOThread(
687 const scoped_refptr<media::VideoFrame>& reserved_frame, 584 const scoped_refptr<media::VideoFrame>& reserved_frame,
585 int frame_rate,
688 base::Time timestamp) { 586 base::Time timestamp) {
689 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 587 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
690 588
691 if (!buffer_pool_.get())
692 return;
693
694 int buffer_id = buffer_pool_->RecognizeReservedBuffer( 589 int buffer_id = buffer_pool_->RecognizeReservedBuffer(
695 reserved_frame->shared_memory_handle()); 590 reserved_frame->shared_memory_handle());
696 if (buffer_id < 0) { 591 if (buffer_id < 0) {
697 NOTREACHED(); 592 NOTREACHED();
698 return; 593 return;
699 } 594 }
700 595
596 media::VideoCaptureFormat frame_format(
597 reserved_frame->coded_size().width(),
598 reserved_frame->coded_size().height(),
599 frame_rate,
600 media::VariableResolutionVideoCaptureDevice);
601
701 int count = 0; 602 int count = 0;
702 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { 603 if (state_ == VIDEO_CAPTURE_STATE_STARTED) {
703 for (ControllerClients::iterator client_it = controller_clients_.begin(); 604 for (ControllerClients::iterator client_it = controller_clients_.begin();
704 client_it != controller_clients_.end(); ++client_it) { 605 client_it != controller_clients_.end(); ++client_it) {
705 if ((*client_it)->session_closed) 606 ControllerClient* client = *client_it;
607 if (client->session_closed)
706 continue; 608 continue;
707 609
708 (*client_it)->event_handler->OnBufferReady((*client_it)->controller_id, 610 bool is_new_buffer = client->known_buffers.insert(buffer_id).second;
709 buffer_id, timestamp); 611 if (is_new_buffer) {
710 (*client_it)->buffers.insert(buffer_id); 612 // On the first use of a buffer on a client, share the memory handle.
613 size_t memory_size = 0;
614 base::SharedMemoryHandle remote_handle = buffer_pool_->ShareToProcess(
615 buffer_id, client->render_process_handle, &memory_size);
616 client->event_handler->OnBufferCreated(client->controller_id,
617 remote_handle,
618 memory_size,
619 buffer_id);
620 }
621
622 client->event_handler->OnBufferReady(client->controller_id,
623 buffer_id, timestamp,
624 frame_format);
625 bool inserted = client->active_buffers.insert(buffer_id).second;
626 DCHECK(!inserted) << "Unexpected duplicate buffer: " << buffer_id;
Ami GONE FROM CHROMIUM 2013/10/17 20:31:45 s/!// ??? (how is this not tripping for you?)
ncarter (slow) 2013/10/22 01:06:21 Was a bug, and caused the tests to fail. It's fixe
711 count++; 627 count++;
712 } 628 }
713 } 629 }
714 630
715 buffer_pool_->HoldForConsumers(buffer_id, count); 631 buffer_pool_->HoldForConsumers(buffer_id, count);
716 } 632 }
717 633
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() { 634 void VideoCaptureController::DoErrorOnIOThread() {
759 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 635 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
760 state_ = VIDEO_CAPTURE_STATE_ERROR; 636 state_ = VIDEO_CAPTURE_STATE_ERROR;
761 ControllerClients::iterator client_it; 637
762 for (client_it = controller_clients_.begin(); 638 for (ControllerClients::iterator client_it = controller_clients_.begin();
763 client_it != controller_clients_.end(); ++client_it) { 639 client_it != controller_clients_.end(); ++client_it) {
764 if ((*client_it)->session_closed) 640 ControllerClient* client = *client_it;
765 continue; 641 if (client->session_closed)
642 continue;
766 643
767 (*client_it)->event_handler->OnError((*client_it)->controller_id); 644 client->event_handler->OnError(client->controller_id);
768 } 645 }
769 } 646 }
770 647
771 void VideoCaptureController::SendFrameInfoAndBuffers(ControllerClient* client) { 648 void VideoCaptureController::DoBufferDestroyedOnIOThread(
649 int buffer_id_to_drop) {
772 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 650 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 651
780 client->event_handler->OnBufferCreated(client->controller_id, 652 for (ControllerClients::iterator client_it = controller_clients_.begin();
781 remote_handle, 653 client_it != controller_clients_.end(); ++client_it) {
782 buffer_pool_->GetMemorySize(), 654 ControllerClient* client = *client_it;
783 buffer_id); 655 if (client->session_closed)
656 continue;
657
658 if (client->known_buffers.erase(buffer_id_to_drop)) {
659 client->event_handler->OnBufferDestroyed(client->controller_id,
660 buffer_id_to_drop);
661 }
784 } 662 }
785 } 663 }
786 664
787 VideoCaptureController::ControllerClient* 665 VideoCaptureController::ControllerClient*
788 VideoCaptureController::FindClient( 666 VideoCaptureController::FindClient(
789 const VideoCaptureControllerID& id, 667 const VideoCaptureControllerID& id,
790 VideoCaptureControllerEventHandler* handler, 668 VideoCaptureControllerEventHandler* handler,
791 const ControllerClients& clients) { 669 const ControllerClients& clients) {
792 for (ControllerClients::const_iterator client_it = clients.begin(); 670 for (ControllerClients::const_iterator client_it = clients.begin();
793 client_it != clients.end(); ++client_it) { 671 client_it != clients.end(); ++client_it) {
(...skipping 17 matching lines...) Expand all
811 } 689 }
812 return NULL; 690 return NULL;
813 } 691 }
814 692
815 int VideoCaptureController::GetClientCount() { 693 int VideoCaptureController::GetClientCount() {
816 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 694 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
817 return controller_clients_.size(); 695 return controller_clients_.size();
818 } 696 }
819 697
820 } // namespace content 698 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698