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 // Implementation notes: This needs to work on a variety of hardware | 5 // Implementation notes: This needs to work on a variety of hardware |
6 // configurations where the speed of the CPU and GPU greatly affect overall | 6 // configurations where the speed of the CPU and GPU greatly affect overall |
7 // performance. Spanning several threads, the process of capturing has been | 7 // performance. Spanning several threads, the process of capturing has been |
8 // split up into four conceptual stages: | 8 // split up into four conceptual stages: |
9 // | 9 // |
10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the client's | 10 // 1. Reserve Buffer: Before a frame can be captured, a slot in the client's |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 void Stop(); | 156 void Stop(); |
157 | 157 |
158 // Signal an error to the client. | 158 // Signal an error to the client. |
159 void ReportError(); | 159 void ReportError(); |
160 | 160 |
161 private: | 161 private: |
162 friend class base::RefCountedThreadSafe<ThreadSafeCaptureOracle>; | 162 friend class base::RefCountedThreadSafe<ThreadSafeCaptureOracle>; |
163 virtual ~ThreadSafeCaptureOracle() {} | 163 virtual ~ThreadSafeCaptureOracle() {} |
164 | 164 |
165 // Callback invoked on completion of all captures. | 165 // Callback invoked on completion of all captures. |
166 void DidCaptureFrame(const scoped_refptr<media::VideoFrame>& frame, | 166 void DidCaptureFrame( |
167 int frame_number, | 167 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, |
168 base::Time timestamp, | 168 int frame_number, |
169 bool success); | 169 base::Time timestamp, |
170 bool success); | |
170 // Protects everything below it. | 171 // Protects everything below it. |
171 base::Lock lock_; | 172 base::Lock lock_; |
172 | 173 |
173 // Recipient of our capture activity. | 174 // Recipient of our capture activity. |
174 scoped_ptr<media::VideoCaptureDevice::Client> client_; | 175 scoped_ptr<media::VideoCaptureDevice::Client> client_; |
175 | 176 |
176 // Makes the decision to capture a frame. | 177 // Makes the decision to capture a frame. |
177 const scoped_ptr<VideoCaptureOracle> oracle_; | 178 const scoped_ptr<VideoCaptureOracle> oracle_; |
178 | 179 |
179 // The resolution at which we're capturing. | 180 // The resolution at which we're capturing. |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
410 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( | 411 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( |
411 VideoCaptureOracle::Event event, | 412 VideoCaptureOracle::Event event, |
412 base::Time event_time, | 413 base::Time event_time, |
413 scoped_refptr<media::VideoFrame>* storage, | 414 scoped_refptr<media::VideoFrame>* storage, |
414 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) { | 415 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback* callback) { |
415 base::AutoLock guard(lock_); | 416 base::AutoLock guard(lock_); |
416 | 417 |
417 if (!client_) | 418 if (!client_) |
418 return false; // Capture is stopped. | 419 return false; // Capture is stopped. |
419 | 420 |
420 scoped_refptr<media::VideoFrame> output_buffer = | 421 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer = |
421 client_->ReserveOutputBuffer(capture_size_); | 422 client_->ReserveOutputBuffer(media::VideoFrame::I420, capture_size_); |
422 const bool should_capture = | 423 const bool should_capture = |
423 oracle_->ObserveEventAndDecideCapture(event, event_time); | 424 oracle_->ObserveEventAndDecideCapture(event, event_time); |
424 const bool content_is_dirty = | 425 const bool content_is_dirty = |
425 (event == VideoCaptureOracle::kCompositorUpdate || | 426 (event == VideoCaptureOracle::kCompositorUpdate || |
426 event == VideoCaptureOracle::kSoftwarePaint); | 427 event == VideoCaptureOracle::kSoftwarePaint); |
427 const char* event_name = | 428 const char* event_name = |
428 (event == VideoCaptureOracle::kTimerPoll ? "poll" : | 429 (event == VideoCaptureOracle::kTimerPoll ? "poll" : |
429 (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" : | 430 (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" : |
430 "paint")); | 431 "paint")); |
431 | 432 |
432 // Consider the various reasons not to initiate a capture. | 433 // Consider the various reasons not to initiate a capture. |
433 if (should_capture && !output_buffer.get()) { | 434 if (should_capture && !output_buffer) { |
434 TRACE_EVENT_INSTANT1("mirroring", | 435 TRACE_EVENT_INSTANT1("mirroring", |
435 "EncodeLimited", | 436 "EncodeLimited", |
436 TRACE_EVENT_SCOPE_THREAD, | 437 TRACE_EVENT_SCOPE_THREAD, |
437 "trigger", | 438 "trigger", |
438 event_name); | 439 event_name); |
439 return false; | 440 return false; |
440 } else if (!should_capture && output_buffer.get()) { | 441 } else if (!should_capture && output_buffer) { |
441 if (content_is_dirty) { | 442 if (content_is_dirty) { |
442 // This is a normal and acceptable way to drop a frame. We've hit our | 443 // This is a normal and acceptable way to drop a frame. We've hit our |
443 // capture rate limit: for example, the content is animating at 60fps but | 444 // capture rate limit: for example, the content is animating at 60fps but |
444 // we're capturing at 30fps. | 445 // we're capturing at 30fps. |
445 TRACE_EVENT_INSTANT1("mirroring", "FpsRateLimited", | 446 TRACE_EVENT_INSTANT1("mirroring", "FpsRateLimited", |
446 TRACE_EVENT_SCOPE_THREAD, | 447 TRACE_EVENT_SCOPE_THREAD, |
447 "trigger", event_name); | 448 "trigger", event_name); |
448 } | 449 } |
449 return false; | 450 return false; |
450 } else if (!should_capture && !output_buffer.get()) { | 451 } else if (!should_capture && !output_buffer) { |
451 // We decided not to capture, but we wouldn't have been able to if we wanted | 452 // We decided not to capture, but we wouldn't have been able to if we wanted |
452 // to because no output buffer was available. | 453 // to because no output buffer was available. |
453 TRACE_EVENT_INSTANT1("mirroring", "NearlyEncodeLimited", | 454 TRACE_EVENT_INSTANT1("mirroring", "NearlyEncodeLimited", |
454 TRACE_EVENT_SCOPE_THREAD, | 455 TRACE_EVENT_SCOPE_THREAD, |
455 "trigger", event_name); | 456 "trigger", event_name); |
456 return false; | 457 return false; |
457 } | 458 } |
458 int frame_number = oracle_->RecordCapture(); | 459 int frame_number = oracle_->RecordCapture(); |
459 TRACE_EVENT_ASYNC_BEGIN2("mirroring", "Capture", output_buffer.get(), | 460 TRACE_EVENT_ASYNC_BEGIN2("mirroring", "Capture", output_buffer.get(), |
460 "frame_number", frame_number, | 461 "frame_number", frame_number, |
461 "trigger", event_name); | 462 "trigger", event_name); |
462 *storage = output_buffer; | 463 |
464 *storage = media::VideoFrame::WrapExternalPackedMemory( | |
465 media::VideoFrame::I420, | |
466 capture_size_, | |
467 gfx::Rect(capture_size_), | |
468 capture_size_, | |
469 static_cast<uint8*>(output_buffer->data()), | |
470 output_buffer->size(), | |
471 base::SharedMemory::NULLHandle(), | |
472 base::TimeDelta(), | |
473 base::Closure()); | |
463 *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame, | 474 *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame, |
464 this, output_buffer, frame_number); | 475 this, |
476 base::Passed(&output_buffer), | |
ncarter (slow)
2013/10/29 18:42:17
I think this ownership scheme will work today, but
sheu
2013/11/05 20:02:10
That actually blew this whole thing wide open. Lo
| |
477 frame_number); | |
465 return true; | 478 return true; |
466 } | 479 } |
467 | 480 |
468 void ThreadSafeCaptureOracle::Stop() { | 481 void ThreadSafeCaptureOracle::Stop() { |
469 base::AutoLock guard(lock_); | 482 base::AutoLock guard(lock_); |
470 client_.reset(); | 483 client_.reset(); |
471 } | 484 } |
472 | 485 |
473 void ThreadSafeCaptureOracle::ReportError() { | 486 void ThreadSafeCaptureOracle::ReportError() { |
474 base::AutoLock guard(lock_); | 487 base::AutoLock guard(lock_); |
475 if (client_) | 488 if (client_) |
476 client_->OnError(); | 489 client_->OnError(); |
477 } | 490 } |
478 | 491 |
479 void ThreadSafeCaptureOracle::DidCaptureFrame( | 492 void ThreadSafeCaptureOracle::DidCaptureFrame( |
480 const scoped_refptr<media::VideoFrame>& frame, | 493 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, |
481 int frame_number, | 494 int frame_number, |
482 base::Time timestamp, | 495 base::Time timestamp, |
483 bool success) { | 496 bool success) { |
484 base::AutoLock guard(lock_); | 497 base::AutoLock guard(lock_); |
485 TRACE_EVENT_ASYNC_END2("mirroring", "Capture", frame.get(), | 498 TRACE_EVENT_ASYNC_END2("mirroring", "Capture", buffer.get(), |
486 "success", success, | 499 "success", success, |
487 "timestamp", timestamp.ToInternalValue()); | 500 "timestamp", timestamp.ToInternalValue()); |
488 | 501 |
489 if (!client_) | 502 if (!client_) |
490 return; // Capture is stopped. | 503 return; // Capture is stopped. |
491 | 504 |
492 if (success) { | 505 if (success) { |
493 if (oracle_->CompleteCapture(frame_number, timestamp)) | 506 if (oracle_->CompleteCapture(frame_number, timestamp)) { |
494 client_->OnIncomingCapturedVideoFrame(frame, timestamp); | 507 client_->OnIncomingCapturedBuffer( |
508 buffer.Pass(), media::VideoFrame::I420, capture_size_, timestamp); | |
509 } | |
495 } | 510 } |
496 } | 511 } |
497 | 512 |
498 bool FrameSubscriber::ShouldCaptureFrame( | 513 bool FrameSubscriber::ShouldCaptureFrame( |
499 base::Time present_time, | 514 base::Time present_time, |
500 scoped_refptr<media::VideoFrame>* storage, | 515 scoped_refptr<media::VideoFrame>* storage, |
501 DeliverFrameCallback* deliver_frame_cb) { | 516 DeliverFrameCallback* deliver_frame_cb) { |
502 TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame", | 517 TRACE_EVENT1("mirroring", "FrameSubscriber::ShouldCaptureFrame", |
503 "instance", this); | 518 "instance", this); |
504 | 519 |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1182 capture_format.height, | 1197 capture_format.height, |
1183 capture_format.frame_rate, | 1198 capture_format.frame_rate, |
1184 client.Pass()); | 1199 client.Pass()); |
1185 } | 1200 } |
1186 | 1201 |
1187 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { | 1202 void WebContentsVideoCaptureDevice::StopAndDeAllocate() { |
1188 impl_->StopAndDeAllocate(); | 1203 impl_->StopAndDeAllocate(); |
1189 } | 1204 } |
1190 | 1205 |
1191 } // namespace content | 1206 } // namespace content |
OLD | NEW |