OLD | NEW |
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 // Notes about usage of this object by VideoCaptureImplManager. | 5 // Notes about usage of this object by VideoCaptureImplManager. |
6 // | 6 // |
7 // VideoCaptureImplManager access this object by using a Unretained() | 7 // VideoCaptureImplManager access this object by using a Unretained() |
8 // binding and tasks on the IO thread. It is then important that | 8 // binding and tasks on the IO thread. It is then important that |
9 // VideoCaptureImpl never post task to itself. All operations must be | 9 // VideoCaptureImpl never post task to itself. All operations must be |
10 // synchronous. | 10 // synchronous. |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 client_buffers_.insert(std::make_pair( | 191 client_buffers_.insert(std::make_pair( |
192 buffer_id, | 192 buffer_id, |
193 new ClientBuffer(shm.Pass(), | 193 new ClientBuffer(shm.Pass(), |
194 length))).second; | 194 length))).second; |
195 DCHECK(inserted); | 195 DCHECK(inserted); |
196 } | 196 } |
197 | 197 |
198 void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) { | 198 void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) { |
199 DCHECK(thread_checker_.CalledOnValidThread()); | 199 DCHECK(thread_checker_.CalledOnValidThread()); |
200 | 200 |
201 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); | 201 const ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); |
202 if (iter == client_buffers_.end()) | 202 if (iter == client_buffers_.end()) |
203 return; | 203 return; |
204 | 204 |
205 DCHECK(!iter->second.get() || iter->second->HasOneRef()) | 205 DCHECK(!iter->second.get() || iter->second->HasOneRef()) |
206 << "Instructed to delete buffer we are still using."; | 206 << "Instructed to delete buffer we are still using."; |
207 client_buffers_.erase(iter); | 207 client_buffers_.erase(iter); |
208 } | 208 } |
209 | 209 |
210 void VideoCaptureImpl::OnBufferReceived(int buffer_id, | 210 void VideoCaptureImpl::OnBufferReceived(int buffer_id, |
211 const gfx::Size& coded_size, | 211 const gfx::Size& coded_size, |
(...skipping 10 matching lines...) Expand all Loading... |
222 if (first_frame_timestamp_.is_null()) | 222 if (first_frame_timestamp_.is_null()) |
223 first_frame_timestamp_ = timestamp; | 223 first_frame_timestamp_ = timestamp; |
224 | 224 |
225 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc | 225 // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |
226 TRACE_EVENT_INSTANT2( | 226 TRACE_EVENT_INSTANT2( |
227 "cast_perf_test", "OnBufferReceived", | 227 "cast_perf_test", "OnBufferReceived", |
228 TRACE_EVENT_SCOPE_THREAD, | 228 TRACE_EVENT_SCOPE_THREAD, |
229 "timestamp", timestamp.ToInternalValue(), | 229 "timestamp", timestamp.ToInternalValue(), |
230 "time_delta", (timestamp - first_frame_timestamp_).ToInternalValue()); | 230 "time_delta", (timestamp - first_frame_timestamp_).ToInternalValue()); |
231 | 231 |
232 ClientBufferMap::iterator iter = client_buffers_.find(buffer_id); | 232 const ClientBufferMap::const_iterator iter = client_buffers_.find(buffer_id); |
233 DCHECK(iter != client_buffers_.end()); | 233 DCHECK(iter != client_buffers_.end()); |
234 scoped_refptr<ClientBuffer> buffer = iter->second; | 234 scoped_refptr<ClientBuffer> buffer = iter->second; |
235 scoped_refptr<media::VideoFrame> frame = | 235 scoped_refptr<media::VideoFrame> frame = |
236 media::VideoFrame::WrapExternalPackedMemory( | 236 media::VideoFrame::WrapExternalPackedMemory( |
237 media::VideoFrame::I420, | 237 media::VideoFrame::I420, |
238 coded_size, | 238 coded_size, |
239 visible_rect, | 239 visible_rect, |
240 gfx::Size(visible_rect.width(), visible_rect.height()), | 240 gfx::Size(visible_rect.width(), visible_rect.height()), |
241 reinterpret_cast<uint8*>(buffer->buffer->memory()), | 241 reinterpret_cast<uint8*>(buffer->buffer->memory()), |
242 buffer->buffer_size, | 242 buffer->buffer_size, |
243 buffer->buffer->handle(), | 243 buffer->buffer->handle(), |
244 0, | 244 0, |
245 timestamp - first_frame_timestamp_, | 245 timestamp - first_frame_timestamp_, |
246 media::BindToCurrentLoop( | 246 media::BindToCurrentLoop( |
247 base::Bind(&VideoCaptureImpl::OnClientBufferFinished, | 247 base::Bind(&VideoCaptureImpl::OnClientBufferFinished, |
248 weak_factory_.GetWeakPtr(), | 248 weak_factory_.GetWeakPtr(), |
249 buffer_id, | 249 buffer_id, |
250 buffer, | 250 buffer, |
251 0))); | 251 0))); |
252 frame->metadata()->MergeInternalValuesFrom(metadata); | 252 frame->metadata()->MergeInternalValuesFrom(metadata); |
253 | 253 |
254 for (const auto& entry : clients_) | 254 for (const auto& client : clients_) |
255 entry.second.deliver_frame_cb.Run(frame, timestamp); | 255 client.second.deliver_frame_cb.Run(frame, timestamp); |
256 } | 256 } |
257 | 257 |
258 void VideoCaptureImpl::OnMailboxBufferReceived( | 258 void VideoCaptureImpl::OnMailboxBufferReceived( |
259 int buffer_id, | 259 int buffer_id, |
260 const gpu::MailboxHolder& mailbox_holder, | 260 const gpu::MailboxHolder& mailbox_holder, |
261 const gfx::Size& packed_frame_size, | 261 const gfx::Size& packed_frame_size, |
262 base::TimeTicks timestamp, | 262 base::TimeTicks timestamp, |
263 const base::DictionaryValue& metadata) { | 263 const base::DictionaryValue& metadata) { |
264 DCHECK(thread_checker_.CalledOnValidThread()); | 264 DCHECK(thread_checker_.CalledOnValidThread()); |
265 | 265 |
266 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { | 266 if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) { |
267 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 0)); | 267 Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 0)); |
268 return; | 268 return; |
269 } | 269 } |
270 | 270 |
271 if (first_frame_timestamp_.is_null()) | 271 if (first_frame_timestamp_.is_null()) |
272 first_frame_timestamp_ = timestamp; | 272 first_frame_timestamp_ = timestamp; |
273 | 273 |
274 scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapNativeTexture( | 274 scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapNativeTexture( |
275 make_scoped_ptr(new gpu::MailboxHolder(mailbox_holder)), | 275 make_scoped_ptr(new gpu::MailboxHolder(mailbox_holder)), |
276 media::BindToCurrentLoop(base::Bind( | 276 media::BindToCurrentLoop(base::Bind( |
277 &VideoCaptureImpl::OnClientBufferFinished, weak_factory_.GetWeakPtr(), | 277 &VideoCaptureImpl::OnClientBufferFinished, weak_factory_.GetWeakPtr(), |
278 buffer_id, scoped_refptr<ClientBuffer>())), | 278 buffer_id, scoped_refptr<ClientBuffer>())), |
279 packed_frame_size, gfx::Rect(packed_frame_size), packed_frame_size, | 279 packed_frame_size, gfx::Rect(packed_frame_size), packed_frame_size, |
280 timestamp - first_frame_timestamp_, false); | 280 timestamp - first_frame_timestamp_, false); |
281 frame->metadata()->MergeInternalValuesFrom(metadata); | 281 frame->metadata()->MergeInternalValuesFrom(metadata); |
282 | 282 |
283 for (const auto& entry : clients_) | 283 for (const auto& client : clients_) |
284 entry.second.deliver_frame_cb.Run(frame, timestamp); | 284 client.second.deliver_frame_cb.Run(frame, timestamp); |
285 } | 285 } |
286 | 286 |
287 void VideoCaptureImpl::OnClientBufferFinished( | 287 void VideoCaptureImpl::OnClientBufferFinished( |
288 int buffer_id, | 288 int buffer_id, |
289 const scoped_refptr<ClientBuffer>& /* ignored_buffer */, | 289 const scoped_refptr<ClientBuffer>& /* ignored_buffer */, |
290 uint32 release_sync_point) { | 290 uint32 release_sync_point) { |
291 DCHECK(thread_checker_.CalledOnValidThread()); | 291 DCHECK(thread_checker_.CalledOnValidThread()); |
292 Send(new VideoCaptureHostMsg_BufferReady( | 292 Send(new VideoCaptureHostMsg_BufferReady( |
293 device_id_, buffer_id, release_sync_point)); | 293 device_id_, buffer_id, release_sync_point)); |
294 } | 294 } |
295 | 295 |
296 void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { | 296 void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) { |
297 DCHECK(thread_checker_.CalledOnValidThread()); | 297 DCHECK(thread_checker_.CalledOnValidThread()); |
298 | 298 |
299 switch (state) { | 299 switch (state) { |
300 case VIDEO_CAPTURE_STATE_STARTED: | 300 case VIDEO_CAPTURE_STATE_STARTED: |
301 // Camera has started in the browser process. Since we have already | 301 // Camera has started in the browser process. Since we have already |
302 // told all clients that we have started there's nothing to do. | 302 // told all clients that we have started there's nothing to do. |
303 break; | 303 break; |
304 case VIDEO_CAPTURE_STATE_STOPPED: | 304 case VIDEO_CAPTURE_STATE_STOPPED: |
305 state_ = VIDEO_CAPTURE_STATE_STOPPED; | 305 state_ = VIDEO_CAPTURE_STATE_STOPPED; |
306 DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_; | 306 DVLOG(1) << "OnStateChanged: stopped!, device_id = " << device_id_; |
307 client_buffers_.clear(); | 307 client_buffers_.clear(); |
308 weak_factory_.InvalidateWeakPtrs(); | 308 weak_factory_.InvalidateWeakPtrs(); |
309 if (!clients_.empty() || !clients_pending_on_restart_.empty()) | 309 if (!clients_.empty() || !clients_pending_on_restart_.empty()) |
310 RestartCapture(); | 310 RestartCapture(); |
311 break; | 311 break; |
312 case VIDEO_CAPTURE_STATE_PAUSED: | 312 case VIDEO_CAPTURE_STATE_PAUSED: |
313 for (ClientInfoMap::iterator it = clients_.begin(); | 313 for (const auto& client : clients_) |
314 it != clients_.end(); ++it) { | 314 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_PAUSED); |
315 it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_PAUSED); | |
316 } | |
317 break; | 315 break; |
318 case VIDEO_CAPTURE_STATE_ERROR: | 316 case VIDEO_CAPTURE_STATE_ERROR: |
319 DVLOG(1) << "OnStateChanged: error!, device_id = " << device_id_; | 317 DVLOG(1) << "OnStateChanged: error!, device_id = " << device_id_; |
320 for (ClientInfoMap::iterator it = clients_.begin(); | 318 for (const auto& client : clients_) |
321 it != clients_.end(); ++it) { | 319 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR); |
322 it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_ERROR); | |
323 } | |
324 clients_.clear(); | 320 clients_.clear(); |
325 state_ = VIDEO_CAPTURE_STATE_ERROR; | 321 state_ = VIDEO_CAPTURE_STATE_ERROR; |
326 break; | 322 break; |
327 case VIDEO_CAPTURE_STATE_ENDED: | 323 case VIDEO_CAPTURE_STATE_ENDED: |
328 DVLOG(1) << "OnStateChanged: ended!, device_id = " << device_id_; | 324 DVLOG(1) << "OnStateChanged: ended!, device_id = " << device_id_; |
329 for (ClientInfoMap::iterator it = clients_.begin(); | 325 for (const auto& client : clients_) { |
330 it != clients_.end(); ++it) { | |
331 // We'll only notify the client that the stream has stopped. | 326 // We'll only notify the client that the stream has stopped. |
332 it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED); | 327 client.second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED); |
333 } | 328 } |
334 clients_.clear(); | 329 clients_.clear(); |
335 state_ = VIDEO_CAPTURE_STATE_ENDED; | 330 state_ = VIDEO_CAPTURE_STATE_ENDED; |
336 break; | 331 break; |
337 default: | 332 default: |
338 break; | 333 break; |
339 } | 334 } |
340 } | 335 } |
341 | 336 |
342 void VideoCaptureImpl::OnDeviceSupportedFormatsEnumerated( | 337 void VideoCaptureImpl::OnDeviceSupportedFormatsEnumerated( |
(...skipping 10 matching lines...) Expand all Loading... |
353 for (size_t i = 0; i < device_formats_in_use_cb_queue_.size(); ++i) | 348 for (size_t i = 0; i < device_formats_in_use_cb_queue_.size(); ++i) |
354 device_formats_in_use_cb_queue_[i].Run(formats_in_use); | 349 device_formats_in_use_cb_queue_[i].Run(formats_in_use); |
355 device_formats_in_use_cb_queue_.clear(); | 350 device_formats_in_use_cb_queue_.clear(); |
356 } | 351 } |
357 | 352 |
358 void VideoCaptureImpl::OnDelegateAdded(int32 device_id) { | 353 void VideoCaptureImpl::OnDelegateAdded(int32 device_id) { |
359 DCHECK(thread_checker_.CalledOnValidThread()); | 354 DCHECK(thread_checker_.CalledOnValidThread()); |
360 DVLOG(1) << "OnDelegateAdded: device_id " << device_id; | 355 DVLOG(1) << "OnDelegateAdded: device_id " << device_id; |
361 | 356 |
362 device_id_ = device_id; | 357 device_id_ = device_id; |
363 for (ClientInfoMap::iterator it = clients_pending_on_filter_.begin(); | 358 ClientInfoMap::iterator it = clients_pending_on_filter_.begin(); |
364 it != clients_pending_on_filter_.end(); ) { | 359 while (it != clients_pending_on_filter_.end()) { |
365 int client_id = it->first; | 360 const int client_id = it->first; |
366 VideoCaptureStateUpdateCB state_update_cb = | 361 const ClientInfo client_info = it->second; |
367 it->second.state_update_cb; | |
368 VideoCaptureDeliverFrameCB deliver_frame_cb = | |
369 it->second.deliver_frame_cb; | |
370 const media::VideoCaptureParams params = it->second.params; | |
371 clients_pending_on_filter_.erase(it++); | 362 clients_pending_on_filter_.erase(it++); |
372 StartCapture(client_id, params, state_update_cb, | 363 StartCapture(client_id, client_info.params, client_info.state_update_cb, |
373 deliver_frame_cb); | 364 client_info.deliver_frame_cb); |
374 } | 365 } |
375 } | 366 } |
376 | 367 |
377 void VideoCaptureImpl::StopDevice() { | 368 void VideoCaptureImpl::StopDevice() { |
378 DCHECK(thread_checker_.CalledOnValidThread()); | 369 DCHECK(thread_checker_.CalledOnValidThread()); |
379 | 370 |
380 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { | 371 if (state_ == VIDEO_CAPTURE_STATE_STARTED) { |
381 state_ = VIDEO_CAPTURE_STATE_STOPPING; | 372 state_ = VIDEO_CAPTURE_STATE_STOPPING; |
382 Send(new VideoCaptureHostMsg_Stop(device_id_)); | 373 Send(new VideoCaptureHostMsg_Stop(device_id_)); |
383 params_.requested_format.frame_size.SetSize(0, 0); | 374 params_.requested_format.frame_size.SetSize(0, 0); |
384 } | 375 } |
385 } | 376 } |
386 | 377 |
387 void VideoCaptureImpl::RestartCapture() { | 378 void VideoCaptureImpl::RestartCapture() { |
388 DCHECK(thread_checker_.CalledOnValidThread()); | 379 DCHECK(thread_checker_.CalledOnValidThread()); |
389 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); | 380 DCHECK_EQ(state_, VIDEO_CAPTURE_STATE_STOPPED); |
390 | 381 |
391 int width = 0; | 382 int width = 0; |
392 int height = 0; | 383 int height = 0; |
393 clients_.insert(clients_pending_on_restart_.begin(), | 384 clients_.insert(clients_pending_on_restart_.begin(), |
394 clients_pending_on_restart_.end()); | 385 clients_pending_on_restart_.end()); |
395 clients_pending_on_restart_.clear(); | 386 clients_pending_on_restart_.clear(); |
396 for (ClientInfoMap::iterator it = clients_.begin(); | 387 for (const auto& client : clients_) { |
397 it != clients_.end(); ++it) { | |
398 width = std::max(width, | 388 width = std::max(width, |
399 it->second.params.requested_format.frame_size.width()); | 389 client.second.params.requested_format.frame_size.width()); |
400 height = std::max(height, | 390 height = std::max( |
401 it->second.params.requested_format.frame_size.height()); | 391 height, client.second.params.requested_format.frame_size.height()); |
402 } | 392 } |
403 params_.requested_format.frame_size.SetSize(width, height); | 393 params_.requested_format.frame_size.SetSize(width, height); |
404 DVLOG(1) << "RestartCapture, " | 394 DVLOG(1) << "RestartCapture, " |
405 << params_.requested_format.frame_size.ToString(); | 395 << params_.requested_format.frame_size.ToString(); |
406 StartCaptureInternal(); | 396 StartCaptureInternal(); |
407 } | 397 } |
408 | 398 |
409 void VideoCaptureImpl::StartCaptureInternal() { | 399 void VideoCaptureImpl::StartCaptureInternal() { |
410 DCHECK(thread_checker_.CalledOnValidThread()); | 400 DCHECK(thread_checker_.CalledOnValidThread()); |
411 DCHECK(device_id_); | 401 DCHECK(device_id_); |
412 | 402 |
413 Send(new VideoCaptureHostMsg_Start(device_id_, session_id_, params_)); | 403 Send(new VideoCaptureHostMsg_Start(device_id_, session_id_, params_)); |
414 state_ = VIDEO_CAPTURE_STATE_STARTED; | 404 state_ = VIDEO_CAPTURE_STATE_STARTED; |
415 } | 405 } |
416 | 406 |
417 void VideoCaptureImpl::Send(IPC::Message* message) { | 407 void VideoCaptureImpl::Send(IPC::Message* message) { |
418 DCHECK(thread_checker_.CalledOnValidThread()); | 408 DCHECK(thread_checker_.CalledOnValidThread()); |
419 message_filter_->Send(message); | 409 message_filter_->Send(message); |
420 } | 410 } |
421 | 411 |
422 bool VideoCaptureImpl::RemoveClient(int client_id, ClientInfoMap* clients) { | 412 bool VideoCaptureImpl::RemoveClient(int client_id, ClientInfoMap* clients) { |
423 DCHECK(thread_checker_.CalledOnValidThread()); | 413 DCHECK(thread_checker_.CalledOnValidThread()); |
424 bool found = false; | 414 bool found = false; |
425 | 415 |
426 ClientInfoMap::iterator it = clients->find(client_id); | 416 const ClientInfoMap::iterator it = clients->find(client_id); |
427 if (it != clients->end()) { | 417 if (it != clients->end()) { |
428 it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED); | 418 it->second.state_update_cb.Run(VIDEO_CAPTURE_STATE_STOPPED); |
429 clients->erase(it); | 419 clients->erase(it); |
430 found = true; | 420 found = true; |
431 } | 421 } |
432 return found; | 422 return found; |
433 } | 423 } |
434 | 424 |
435 } // namespace content | 425 } // namespace content |
OLD | NEW |