Index: media/capture/screen_capture_device_core.cc |
diff --git a/content/browser/media/capture/content_video_capture_device_core.cc b/media/capture/screen_capture_device_core.cc |
similarity index 20% |
copy from content/browser/media/capture/content_video_capture_device_core.cc |
copy to media/capture/screen_capture_device_core.cc |
index 336bcd63a7f578d4e757b8de39a5c5d7688dff55..a8993e7ef897b64691500c27b04eedcfbf7d2293 100644 |
--- a/content/browser/media/capture/content_video_capture_device_core.cc |
+++ b/media/capture/screen_capture_device_core.cc |
@@ -2,228 +2,30 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "content/browser/media/capture/content_video_capture_device_core.h" |
+#include "media/capture/screen_capture_device_core.h" |
-#include "base/basictypes.h" |
#include "base/bind.h" |
-#include "base/callback_forward.h" |
-#include "base/callback_helpers.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/memory/weak_ptr.h" |
-#include "base/metrics/histogram.h" |
-#include "base/sequenced_task_runner.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/stringprintf.h" |
-#include "base/synchronization/lock.h" |
-#include "base/threading/thread.h" |
#include "base/threading/thread_checker.h" |
-#include "base/time/time.h" |
-#include "base/trace_event/trace_event.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "media/base/video_capture_types.h" |
-#include "media/base/video_frame.h" |
-#include "media/base/video_frame_metadata.h" |
-#include "media/base/video_util.h" |
-#include "ui/gfx/geometry/rect.h" |
-namespace content { |
+namespace media { |
namespace { |
-void DeleteCaptureMachineOnUIThread( |
+void DeleteCaptureMachine( |
scoped_ptr<VideoCaptureMachine> capture_machine) { |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- |
capture_machine.reset(); |
} |
} // namespace |
-ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( |
- scoped_ptr<media::VideoCaptureDevice::Client> client, |
- const media::VideoCaptureParams& params) |
- : client_(client.Pass()), |
- oracle_(base::TimeDelta::FromMicroseconds( |
- static_cast<int64>(1000000.0 / params.requested_format.frame_rate + |
- 0.5 /* to round to nearest int */))), |
- params_(params), |
- resolution_chooser_(params.requested_format.frame_size, |
- params.resolution_change_policy) {} |
- |
-ThreadSafeCaptureOracle::~ThreadSafeCaptureOracle() {} |
- |
-bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( |
- VideoCaptureOracle::Event event, |
- const gfx::Rect& damage_rect, |
- base::TimeTicks event_time, |
- scoped_refptr<media::VideoFrame>* storage, |
- CaptureFrameCallback* callback) { |
- // Grab the current time before waiting to acquire the |lock_|. |
- const base::TimeTicks capture_begin_time = base::TimeTicks::Now(); |
- |
- base::AutoLock guard(lock_); |
- |
- if (!client_) |
- return false; // Capture is stopped. |
- |
- const gfx::Size visible_size = resolution_chooser_.capture_size(); |
- // Always round up the coded size to multiple of 16 pixels. |
- // See http://crbug.com/402151. |
- const gfx::Size coded_size((visible_size.width() + 15) & ~15, |
- (visible_size.height() + 15) & ~15); |
- |
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer( |
- client_->ReserveOutputBuffer(params_.requested_format.pixel_format, |
- coded_size)); |
- // TODO(miu): Use current buffer pool utilization to drive automatic video |
- // resolution changes. http://crbug.com/156767. |
- VLOG(2) << "Current buffer pool utilization is " |
- << (client_->GetBufferPoolUtilization() * 100.0) << '%'; |
- |
- const bool should_capture = |
- oracle_.ObserveEventAndDecideCapture(event, damage_rect, event_time); |
- |
- const char* event_name = |
- (event == VideoCaptureOracle::kTimerPoll ? "poll" : |
- (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" : |
- "unknown")); |
- |
- // Consider the various reasons not to initiate a capture. |
- if (should_capture && !output_buffer.get()) { |
- TRACE_EVENT_INSTANT1("gpu.capture", |
- "PipelineLimited", |
- TRACE_EVENT_SCOPE_THREAD, |
- "trigger", |
- event_name); |
- return false; |
- } else if (!should_capture && output_buffer.get()) { |
- if (event == VideoCaptureOracle::kCompositorUpdate) { |
- // This is a normal and acceptable way to drop a frame. We've hit our |
- // capture rate limit: for example, the content is animating at 60fps but |
- // we're capturing at 30fps. |
- TRACE_EVENT_INSTANT1("gpu.capture", "FpsRateLimited", |
- TRACE_EVENT_SCOPE_THREAD, |
- "trigger", event_name); |
- } |
- return false; |
- } else if (!should_capture && !output_buffer.get()) { |
- // We decided not to capture, but we wouldn't have been able to if we wanted |
- // to because no output buffer was available. |
- TRACE_EVENT_INSTANT1("gpu.capture", "NearlyPipelineLimited", |
- TRACE_EVENT_SCOPE_THREAD, |
- "trigger", event_name); |
- return false; |
- } |
- int frame_number = oracle_.RecordCapture(); |
- TRACE_EVENT_ASYNC_BEGIN2("gpu.capture", "Capture", output_buffer.get(), |
- "frame_number", frame_number, |
- "trigger", event_name); |
- // NATIVE_TEXTURE frames wrap a texture mailbox, which we don't have at the |
- // moment. We do not construct those frames. |
- if (params_.requested_format.pixel_format != media::PIXEL_FORMAT_TEXTURE) { |
- *storage = media::VideoFrame::WrapExternalData( |
- media::VideoFrame::I420, |
- coded_size, |
- gfx::Rect(visible_size), |
- visible_size, |
- static_cast<uint8*>(output_buffer->data()), |
- output_buffer->size(), |
- base::TimeDelta()); |
- DCHECK(*storage); |
- } |
- *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame, |
- this, |
- frame_number, |
- base::Passed(&output_buffer), |
- capture_begin_time, |
- oracle_.estimated_frame_duration()); |
- return true; |
-} |
- |
-gfx::Size ThreadSafeCaptureOracle::GetCaptureSize() const { |
- base::AutoLock guard(lock_); |
- return resolution_chooser_.capture_size(); |
-} |
- |
-void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) { |
- base::AutoLock guard(lock_); |
- resolution_chooser_.SetSourceSize(source_size); |
- VLOG(1) << "Source size changed to " << source_size.ToString() |
- << " --> Capture size is now " |
- << resolution_chooser_.capture_size().ToString(); |
-} |
- |
-void ThreadSafeCaptureOracle::Stop() { |
- base::AutoLock guard(lock_); |
- client_.reset(); |
-} |
- |
-void ThreadSafeCaptureOracle::ReportError(const std::string& reason) { |
- base::AutoLock guard(lock_); |
- if (client_) |
- client_->OnError(reason); |
-} |
- |
-void ThreadSafeCaptureOracle::DidCaptureFrame( |
- int frame_number, |
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer, |
- base::TimeTicks capture_begin_time, |
- base::TimeDelta estimated_frame_duration, |
- const scoped_refptr<media::VideoFrame>& frame, |
- base::TimeTicks timestamp, |
- bool success) { |
- base::AutoLock guard(lock_); |
- TRACE_EVENT_ASYNC_END2("gpu.capture", "Capture", buffer.get(), |
- "success", success, |
- "timestamp", timestamp.ToInternalValue()); |
- |
- if (oracle_.CompleteCapture(frame_number, success, ×tamp)) { |
- TRACE_EVENT_INSTANT0("gpu.capture", "CaptureSucceeded", |
- TRACE_EVENT_SCOPE_THREAD); |
- |
- if (!client_) |
- return; // Capture is stopped. |
- |
- frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
- params_.requested_format.frame_rate); |
- frame->metadata()->SetTimeTicks( |
- media::VideoFrameMetadata::CAPTURE_BEGIN_TIME, capture_begin_time); |
- frame->metadata()->SetTimeTicks( |
- media::VideoFrameMetadata::CAPTURE_END_TIME, base::TimeTicks::Now()); |
- frame->metadata()->SetTimeDelta(media::VideoFrameMetadata::FRAME_DURATION, |
- estimated_frame_duration); |
- |
- frame->AddDestructionObserver(base::Bind( |
- &ThreadSafeCaptureOracle::DidConsumeFrame, |
- this, |
- frame_number, |
- frame->metadata())); |
- |
- client_->OnIncomingCapturedVideoFrame(buffer.Pass(), frame, timestamp); |
- } |
-} |
- |
-void ThreadSafeCaptureOracle::DidConsumeFrame( |
- int frame_number, |
- const media::VideoFrameMetadata* metadata) { |
- // Note: This function may be called on any thread by the VideoFrame |
- // destructor. |metadata| is still valid for read-access at this point. |
- double utilization = -1.0; |
- if (metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, |
- &utilization) && |
- utilization >= 0.0) { |
- VLOG(2) << "Consumer resource utilization for frame " << frame_number |
- << ": " << utilization; |
- } |
- |
- // TODO(miu): Use |utilization| to drive automatic video resolution changes. |
- // http://crbug.com/156767. |
-} |
- |
-void ContentVideoCaptureDeviceCore::AllocateAndStart( |
- const media::VideoCaptureParams& params, |
- scoped_ptr<media::VideoCaptureDevice::Client> client) { |
+void ScreenCaptureDeviceCore::AllocateAndStart( |
+ const VideoCaptureParams& params, |
+ scoped_ptr<VideoCaptureDevice::Client> client) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
if (state_ != kIdle) { |
@@ -239,8 +41,8 @@ void ContentVideoCaptureDeviceCore::AllocateAndStart( |
return; |
} |
- if (params.requested_format.pixel_format != media::PIXEL_FORMAT_I420 && |
- params.requested_format.pixel_format != media::PIXEL_FORMAT_TEXTURE) { |
+ if (params.requested_format.pixel_format != PIXEL_FORMAT_I420 && |
+ params.requested_format.pixel_format != PIXEL_FORMAT_TEXTURE) { |
std::string error_msg = base::StringPrintf( |
"unsupported format: %d", params.requested_format.pixel_format); |
DVLOG(1) << error_msg; |
@@ -258,20 +60,15 @@ void ContentVideoCaptureDeviceCore::AllocateAndStart( |
oracle_proxy_ = new ThreadSafeCaptureOracle(client.Pass(), params); |
- // Starts the capture machine asynchronously. |
- BrowserThread::PostTaskAndReplyWithResult( |
- BrowserThread::UI, |
- FROM_HERE, |
- base::Bind(&VideoCaptureMachine::Start, |
- base::Unretained(capture_machine_.get()), |
- oracle_proxy_, |
- params), |
- base::Bind(&ContentVideoCaptureDeviceCore::CaptureStarted, AsWeakPtr())); |
+ capture_machine_->Start( |
+ oracle_proxy_, |
+ params, |
+ base::Bind(&ScreenCaptureDeviceCore::CaptureStarted, AsWeakPtr())); |
TransitionStateTo(kCapturing); |
} |
-void ContentVideoCaptureDeviceCore::StopAndDeAllocate() { |
+void ScreenCaptureDeviceCore::StopAndDeAllocate() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
if (state_ != kCapturing) |
@@ -282,15 +79,10 @@ void ContentVideoCaptureDeviceCore::StopAndDeAllocate() { |
TransitionStateTo(kIdle); |
- // Stops the capture machine asynchronously. |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, base::Bind( |
- &VideoCaptureMachine::Stop, |
- base::Unretained(capture_machine_.get()), |
- base::Bind(&base::DoNothing))); |
+ capture_machine_->Stop(base::Bind(&base::DoNothing)); |
} |
-void ContentVideoCaptureDeviceCore::CaptureStarted(bool success) { |
+void ScreenCaptureDeviceCore::CaptureStarted(bool success) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
if (!success) { |
std::string reason("Failed to start capture machine."); |
@@ -299,31 +91,24 @@ void ContentVideoCaptureDeviceCore::CaptureStarted(bool success) { |
} |
} |
-ContentVideoCaptureDeviceCore::ContentVideoCaptureDeviceCore( |
+ScreenCaptureDeviceCore::ScreenCaptureDeviceCore( |
scoped_ptr<VideoCaptureMachine> capture_machine) |
: state_(kIdle), |
capture_machine_(capture_machine.Pass()) { |
DCHECK(capture_machine_.get()); |
} |
-ContentVideoCaptureDeviceCore::~ContentVideoCaptureDeviceCore() { |
+ScreenCaptureDeviceCore::~ScreenCaptureDeviceCore() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
DCHECK_NE(state_, kCapturing); |
- // If capture_machine is not NULL, then we need to return to the UI thread to |
- // safely stop the capture machine. |
if (capture_machine_) { |
- VideoCaptureMachine* capture_machine_ptr = capture_machine_.get(); |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&VideoCaptureMachine::Stop, |
- base::Unretained(capture_machine_ptr), |
- base::Bind(&DeleteCaptureMachineOnUIThread, |
- base::Passed(&capture_machine_)))); |
+ capture_machine_->Stop(base::Bind(&DeleteCaptureMachine, |
+ base::Passed(&capture_machine_))); |
} |
- DVLOG(1) << "ContentVideoCaptureDeviceCore@" << this << " destroying."; |
+ DVLOG(1) << "ScreenCaptureDeviceCore@" << this << " destroying."; |
} |
-void ContentVideoCaptureDeviceCore::TransitionStateTo(State next_state) { |
+void ScreenCaptureDeviceCore::TransitionStateTo(State next_state) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
#ifndef NDEBUG |
@@ -337,7 +122,7 @@ void ContentVideoCaptureDeviceCore::TransitionStateTo(State next_state) { |
state_ = next_state; |
} |
-void ContentVideoCaptureDeviceCore::Error(const std::string& reason) { |
+void ScreenCaptureDeviceCore::Error(const std::string& reason) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
if (state_ == kIdle) |
@@ -350,4 +135,4 @@ void ContentVideoCaptureDeviceCore::Error(const std::string& reason) { |
TransitionStateTo(kError); |
} |
-} // namespace content |
+} // namespace media |