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

Unified Diff: content/browser/media/capture/desktop_capture_device.cc

Issue 1135823004: Implement all resolution change policies for desktop and tab capture. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@resolution_change_policy_constraints_ITEM1_CR1
Patch Set: Addressed Wez's second round comments. Created 5 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/media/capture/desktop_capture_device.cc
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc
index a11e473e83cf6497e49952e5c594ad88a317100a..e42a678daff3cf9365a47848e9b1f45848dc81f2 100644
--- a/content/browser/media/capture/desktop_capture_device.cc
+++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -12,6 +12,7 @@
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/timer/timer.h"
+#include "content/browser/media/capture/capture_resolution_chooser.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
@@ -72,11 +73,6 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
webrtc::SharedMemory* CreateSharedMemory(size_t size) override;
void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
- // Chooses new output properties based on the supplied source size and the
- // properties requested to Allocate(), and dispatches OnFrameInfo[Changed]
- // notifications.
- void RefreshCaptureFormat(const webrtc::DesktopSize& frame_size);
-
// Method that is scheduled on |task_runner_| to be called on regular interval
// to capture a frame.
void OnCaptureTimer();
@@ -97,24 +93,20 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
// on the task_runner_ thread.
scoped_ptr<Client> client_;
- // Requested video capture format (width, height, frame rate, etc).
- media::VideoCaptureParams requested_params_;
-
- // Actual video capture format being generated.
- media::VideoCaptureFormat capture_format_;
+ // Requested video capture frame rate.
+ float requested_frame_rate_;
// Size of frame most recently captured from the source.
webrtc::DesktopSize previous_frame_size_;
+ // Determines the size of frames to deliver to the |client_|.
+ scoped_ptr<CaptureResolutionChooser> resolution_chooser_;
+
// DesktopFrame into which captured frames are down-scaled and/or letterboxed,
// depending upon the caller's requested capture capabilities. If frames can
// be returned to the caller directly then this is NULL.
scoped_ptr<webrtc::DesktopFrame> output_frame_;
- // Sub-rectangle of |output_frame_| into which the source will be scaled
- // and/or letterboxed.
- webrtc::DesktopRect output_rect_;
-
// Timer used to capture the frame.
base::OneShotTimer<Core> capture_timer_;
@@ -167,12 +159,10 @@ void DesktopCaptureDevice::Core::AllocateAndStart(
DCHECK(!client_.get());
client_ = client.Pass();
- requested_params_ = params;
-
- capture_format_ = requested_params_.requested_format;
-
- // This capturer always outputs ARGB, non-interlaced.
- capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB;
+ requested_frame_rate_ = params.requested_format.frame_rate;
+ resolution_chooser_.reset(new CaptureResolutionChooser(
+ params.requested_format.frame_size,
+ params.resolution_change_policy));
power_save_blocker_.reset(
PowerSaveBlocker::Create(
@@ -238,16 +228,29 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
+ // If the frame size has changed, drop the output frame (if any), and
+ // determine the new output size.
+ if (!previous_frame_size_.equals(frame->size())) {
+ output_frame_.reset();
+ resolution_chooser_->SetSourceSize(gfx::Size(frame->size().width(),
+ frame->size().height()));
+ previous_frame_size_ = frame->size();
+ }
+ // Align to 2x2 pixel boundaries, as required by OnIncomingCapturedData() so
+ // it can convert the frame to I420 format.
+ const webrtc::DesktopSize output_size(
+ resolution_chooser_->capture_size().width() & ~1,
+ resolution_chooser_->capture_size().height() & ~1);
+ if (output_size.is_empty())
+ return;
+
// On OSX We receive a 1x1 frame when the shared window is minimized. It
// cannot be subsampled to I420 and will be dropped downstream. So we replace
// it with a black frame to avoid the video appearing frozen at the last
// frame.
if (frame->size().width() == 1 || frame->size().height() == 1) {
if (!black_frame_.get()) {
- black_frame_.reset(
- new webrtc::BasicDesktopFrame(
- webrtc::DesktopSize(capture_format_.frame_size.width(),
- capture_format_.frame_size.height())));
+ black_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
memset(black_frame_->data(),
0,
black_frame_->stride() * black_frame_->size().height());
@@ -256,11 +259,6 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
frame = black_frame_.get();
}
- // Handle initial frame size and size changes.
- RefreshCaptureFormat(frame->size());
-
- webrtc::DesktopSize output_size(capture_format_.frame_size.width(),
- capture_format_.frame_size.height());
size_t output_bytes = output_size.width() * output_size.height() *
webrtc::DesktopFrame::kBytesPerPixel;
const uint8_t* output_data = NULL;
@@ -270,7 +268,7 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
// match the output size.
// Allocate a buffer of the correct size to scale the frame into.
- // |output_frame_| is cleared whenever |output_rect_| changes, so we don't
+ // |output_frame_| is cleared whenever the output size changes, so we don't
// need to worry about clearing out stale pixel data in letterboxed areas.
if (!output_frame_) {
output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
@@ -280,13 +278,15 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
// TODO(wez): Optimize this to scale only changed portions of the output,
// using ARGBScaleClip().
+ const webrtc::DesktopRect output_rect =
+ ComputeLetterboxRect(output_size, frame->size());
uint8_t* output_rect_data = output_frame_->data() +
- output_frame_->stride() * output_rect_.top() +
- webrtc::DesktopFrame::kBytesPerPixel * output_rect_.left();
+ output_frame_->stride() * output_rect.top() +
+ webrtc::DesktopFrame::kBytesPerPixel * output_rect.left();
libyuv::ARGBScale(frame->data(), frame->stride(),
frame->size().width(), frame->size().height(),
output_rect_data, output_frame_->stride(),
- output_rect_.width(), output_rect_.height(),
+ output_rect.width(), output_rect.height(),
libyuv::kFilterBilinear);
output_data = output_frame_->data();
} else if (IsFrameUnpackedOrInverted(frame)) {
@@ -311,49 +311,14 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
}
client_->OnIncomingCapturedData(
- output_data, output_bytes, capture_format_, 0, base::TimeTicks::Now());
-}
-
-void DesktopCaptureDevice::Core::RefreshCaptureFormat(
- const webrtc::DesktopSize& frame_size) {
- if (previous_frame_size_.equals(frame_size))
- return;
-
- // Clear the output frame, if any, since it will either need resizing, or
- // clearing of stale data in letterbox areas, anyway.
- output_frame_.reset();
-
- if (previous_frame_size_.is_empty() ||
- requested_params_.resolution_change_policy ==
- media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT) {
- // If this is the first frame, or the receiver supports variable resolution
- // then determine the output size by treating the requested width & height
- // as maxima.
- if (frame_size.width() >
- requested_params_.requested_format.frame_size.width() ||
- frame_size.height() >
- requested_params_.requested_format.frame_size.height()) {
- output_rect_ = ComputeLetterboxRect(
- webrtc::DesktopSize(
- requested_params_.requested_format.frame_size.width(),
- requested_params_.requested_format.frame_size.height()),
- frame_size);
- output_rect_.Translate(-output_rect_.left(), -output_rect_.top());
- } else {
- output_rect_ = webrtc::DesktopRect::MakeSize(frame_size);
- }
- capture_format_.frame_size.SetSize(output_rect_.width(),
- output_rect_.height());
- } else {
- // Otherwise the output frame size cannot change, so just scale and
- // letterbox.
- output_rect_ = ComputeLetterboxRect(
- webrtc::DesktopSize(capture_format_.frame_size.width(),
- capture_format_.frame_size.height()),
- frame_size);
- }
-
- previous_frame_size_ = frame_size;
+ output_data,
+ output_bytes,
+ media::VideoCaptureFormat(gfx::Size(output_size.width(),
+ output_size.height()),
+ requested_frame_rate_,
+ media::PIXEL_FORMAT_ARGB),
+ 0,
+ base::TimeTicks::Now());
}
void DesktopCaptureDevice::Core::OnCaptureTimer() {
@@ -375,7 +340,8 @@ void DesktopCaptureDevice::Core::CaptureFrameAndScheduleNext() {
// Limit frame-rate to reduce CPU consumption.
base::TimeDelta capture_period = std::max(
(last_capture_duration * 100) / kMaximumCpuConsumptionPercentage,
- base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate);
+ base::TimeDelta::FromMicroseconds(static_cast<int64>(
+ 1000000.0 / requested_frame_rate_ + 0.5 /* round to nearest int */)));
// Schedule a task for the next frame.
capture_timer_.Start(FROM_HERE, capture_period - last_capture_duration,

Powered by Google App Engine
This is Rietveld 408576698