| 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 415096a0abc6b9d0a733a3390317de2625c49f8e..0bdbfe4aa77e6826b516097bc0af3780bd436ee2 100644
|
| --- a/content/browser/media/capture/desktop_capture_device.cc
|
| +++ b/content/browser/media/capture/desktop_capture_device.cc
|
| @@ -75,9 +75,10 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
|
| void SetNotificationWindowId(gfx::NativeViewId window_id);
|
|
|
| private:
|
| -
|
| - // webrtc::DesktopCapturer::Callback interface
|
| - void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
|
| + // webrtc::DesktopCapturer::Callback interface.
|
| + void OnCaptureResult(
|
| + webrtc::DesktopCapturer::Result result,
|
| + std::unique_ptr<webrtc::DesktopFrame> frame) override;
|
|
|
| // Method that is scheduled on |task_runner_| to be called on regular interval
|
| // to capture a frame.
|
| @@ -190,28 +191,32 @@ void DesktopCaptureDevice::Core::SetNotificationWindowId(
|
| desktop_capturer_->SetExcludedWindow(window_id);
|
| }
|
|
|
| -void DesktopCaptureDevice::Core::OnCaptureCompleted(
|
| - webrtc::DesktopFrame* frame) {
|
| +void DesktopCaptureDevice::Core::OnCaptureResult(
|
| + webrtc::DesktopCapturer::Result result,
|
| + std::unique_ptr<webrtc::DesktopFrame> frame) {
|
| DCHECK(task_runner_->BelongsToCurrentThread());
|
| DCHECK(capture_in_progress_);
|
| + capture_in_progress_ = false;
|
| +
|
| + bool success = result == webrtc::DesktopCapturer::Result::SUCCESS;
|
|
|
| if (!first_capture_returned_) {
|
| first_capture_returned_ = true;
|
| if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
|
| - IncrementDesktopCaptureCounter(frame ? FIRST_SCREEN_CAPTURE_SUCCEEDED
|
| - : FIRST_SCREEN_CAPTURE_FAILED);
|
| + IncrementDesktopCaptureCounter(success ? FIRST_SCREEN_CAPTURE_SUCCEEDED
|
| + : FIRST_SCREEN_CAPTURE_FAILED);
|
| } else {
|
| - IncrementDesktopCaptureCounter(frame ? FIRST_WINDOW_CAPTURE_SUCCEEDED
|
| - : FIRST_WINDOW_CAPTURE_FAILED);
|
| + IncrementDesktopCaptureCounter(success ? FIRST_WINDOW_CAPTURE_SUCCEEDED
|
| + : FIRST_WINDOW_CAPTURE_FAILED);
|
| }
|
| }
|
|
|
| - capture_in_progress_ = false;
|
| -
|
| - if (!frame) {
|
| - client_->OnError(FROM_HERE, "Failed to capture a frame.");
|
| + if (!success) {
|
| + if (result == webrtc::DesktopCapturer::Result::ERROR_PERMANENT)
|
| + client_->OnError(FROM_HERE, "The desktop capturer has failed.");
|
| return;
|
| }
|
| + DCHECK(frame);
|
|
|
| if (!client_)
|
| return;
|
| @@ -227,8 +232,6 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
|
| UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
|
| }
|
|
|
| - std::unique_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())) {
|
| @@ -245,26 +248,22 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
|
| 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_) {
|
| + size_t output_bytes = output_size.width() * output_size.height() *
|
| + webrtc::DesktopFrame::kBytesPerPixel;
|
| + const uint8_t* output_data = nullptr;
|
| +
|
| + if (frame->size().equals(webrtc::DesktopSize(1, 1))) {
|
| + // 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 (!black_frame_ || !black_frame_->size().equals(output_size)) {
|
| black_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
|
| - memset(black_frame_->data(),
|
| - 0,
|
| + memset(black_frame_->data(), 0,
|
| black_frame_->stride() * black_frame_->size().height());
|
| }
|
| - owned_frame.reset();
|
| - frame = black_frame_.get();
|
| - }
|
| -
|
| - size_t output_bytes = output_size.width() * output_size.height() *
|
| - webrtc::DesktopFrame::kBytesPerPixel;
|
| - const uint8_t* output_data = NULL;
|
| -
|
| - if (!frame->size().equals(output_size)) {
|
| + output_data = black_frame_->data();
|
| + } else if (!frame->size().equals(output_size)) {
|
| // Down-scale and/or letterbox to the target format if the frame does not
|
| // match the output size.
|
|
|
| @@ -281,16 +280,14 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
|
| // 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();
|
| - libyuv::ARGBScale(frame->data(), frame->stride(),
|
| - frame->size().width(), frame->size().height(),
|
| - output_rect_data, output_frame_->stride(),
|
| - output_rect.width(), output_rect.height(),
|
| - libyuv::kFilterBilinear);
|
| + uint8_t* output_rect_data =
|
| + output_frame_->GetFrameDataAtPos(output_rect.top_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(), libyuv::kFilterBilinear);
|
| output_data = output_frame_->data();
|
| - } else if (IsFrameUnpackedOrInverted(frame)) {
|
| + } else if (IsFrameUnpackedOrInverted(frame.get())) {
|
| // If |frame| is not packed top-to-bottom then create a packed top-to-bottom
|
| // copy.
|
| // This is required if the frame is inverted (see crbug.com/306876), or if
|
| @@ -300,10 +297,8 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
|
| memset(output_frame_->data(), 0, output_bytes);
|
| }
|
|
|
| - output_frame_->CopyPixelsFrom(
|
| - *frame,
|
| - webrtc::DesktopVector(),
|
| - webrtc::DesktopRect::MakeSize(frame->size()));
|
| + output_frame_->CopyPixelsFrom(*frame, webrtc::DesktopVector(),
|
| + webrtc::DesktopRect::MakeSize(frame->size()));
|
| output_data = output_frame_->data();
|
| } else {
|
| // If the captured frame matches the output size, we can return the pixel
|
|
|