[DesktopCapturer] FallbackDesktopCapturerWrapper and its tests
FallbackDesktopCapturerWrapper is a DesktopCapturer implementation, which owns two DesktopCapturer implementations. If the main DesktopCapturer fails, it uses the secondary capturer. The logic is now used in ScreenCapturerWinMagnifier, and it can also be shared in ScreenCapturerWinDirectx to fallback to Gdi capturer on privilege prompt or login screen. BUG=684937 Review-Url: https://codereview.webrtc.org/2697453002 Cr-Commit-Position: refs/heads/master@{#16677}
This commit is contained in:
parent
4ef903d3db
commit
8fefe9889d
@ -63,6 +63,7 @@ if (rtc_include_tests) {
|
||||
"desktop_frame_rotation_unittest.cc",
|
||||
"desktop_region_unittest.cc",
|
||||
"differ_block_unittest.cc",
|
||||
"fallback_desktop_capturer_wrapper_unittest.cc",
|
||||
"mouse_cursor_monitor_unittest.cc",
|
||||
"rgba_color_unittest.cc",
|
||||
"test_utils.cc",
|
||||
@ -185,6 +186,8 @@ rtc_static_library("desktop_capture") {
|
||||
"desktop_frame_win.h",
|
||||
"differ_block.cc",
|
||||
"differ_block.h",
|
||||
"fallback_desktop_capturer_wrapper.cc",
|
||||
"fallback_desktop_capturer_wrapper.h",
|
||||
"mac/desktop_configuration.h",
|
||||
"mac/desktop_configuration.mm",
|
||||
"mac/desktop_configuration_monitor.cc",
|
||||
|
||||
@ -14,17 +14,21 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
FakeDesktopCapturer::FakeDesktopCapturer()
|
||||
: callback_(nullptr),
|
||||
result_(DesktopCapturer::Result::SUCCESS),
|
||||
generator_(nullptr) {}
|
||||
|
||||
FakeDesktopCapturer::FakeDesktopCapturer() = default;
|
||||
FakeDesktopCapturer::~FakeDesktopCapturer() = default;
|
||||
|
||||
void FakeDesktopCapturer::set_result(DesktopCapturer::Result result) {
|
||||
result_ = result;
|
||||
}
|
||||
|
||||
int FakeDesktopCapturer::num_frames_captured() const {
|
||||
return num_frames_captured_;
|
||||
}
|
||||
|
||||
int FakeDesktopCapturer::num_capture_attempts() const {
|
||||
return num_capture_attempts_;
|
||||
}
|
||||
|
||||
// Uses the |generator| provided as DesktopFrameGenerator, FakeDesktopCapturer
|
||||
// does
|
||||
// not take the ownership of |generator|.
|
||||
@ -38,10 +42,17 @@ void FakeDesktopCapturer::Start(DesktopCapturer::Callback* callback) {
|
||||
}
|
||||
|
||||
void FakeDesktopCapturer::CaptureFrame() {
|
||||
num_capture_attempts_++;
|
||||
if (generator_) {
|
||||
if (result_ != DesktopCapturer::Result::SUCCESS) {
|
||||
callback_->OnCaptureResult(result_, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<DesktopFrame> frame(
|
||||
generator_->GetNextFrame(shared_memory_factory_.get()));
|
||||
if (frame) {
|
||||
num_frames_captured_++;
|
||||
callback_->OnCaptureResult(result_, std::move(frame));
|
||||
} else {
|
||||
callback_->OnCaptureResult(DesktopCapturer::Result::ERROR_TEMPORARY,
|
||||
|
||||
@ -43,6 +43,14 @@ class FakeDesktopCapturer : public DesktopCapturer {
|
||||
// does not take the ownership of |generator|.
|
||||
void set_frame_generator(DesktopFrameGenerator* generator);
|
||||
|
||||
// Count of DesktopFrame(s) have been returned by this instance. This field
|
||||
// would never be negative.
|
||||
int num_frames_captured() const;
|
||||
|
||||
// Count of CaptureFrame() calls have been made. This field would never be
|
||||
// negative.
|
||||
int num_capture_attempts() const;
|
||||
|
||||
// DesktopCapturer interface
|
||||
void Start(DesktopCapturer::Callback* callback) override;
|
||||
void CaptureFrame() override;
|
||||
@ -55,10 +63,12 @@ class FakeDesktopCapturer : public DesktopCapturer {
|
||||
static constexpr DesktopCapturer::SourceId kWindowId = 1378277495;
|
||||
static constexpr DesktopCapturer::SourceId kScreenId = 1378277496;
|
||||
|
||||
DesktopCapturer::Callback* callback_;
|
||||
DesktopCapturer::Callback* callback_ = nullptr;
|
||||
std::unique_ptr<SharedMemoryFactory> shared_memory_factory_;
|
||||
DesktopCapturer::Result result_;
|
||||
DesktopFrameGenerator* generator_;
|
||||
DesktopCapturer::Result result_ = Result::SUCCESS;
|
||||
DesktopFrameGenerator* generator_ = nullptr;
|
||||
int num_frames_captured_ = 0;
|
||||
int num_capture_attempts_ = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/desktop_capture/fallback_desktop_capturer_wrapper.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
// Implementation to share a SharedMemoryFactory between DesktopCapturer
|
||||
// instances. This class is designed for synchronized DesktopCapturer
|
||||
// implementations only.
|
||||
class SharedMemoryFactoryProxy : public SharedMemoryFactory {
|
||||
public:
|
||||
// Users should maintain the lifetime of |factory| to ensure it overlives
|
||||
// current instance.
|
||||
static std::unique_ptr<SharedMemoryFactory> Create(
|
||||
SharedMemoryFactory* factory);
|
||||
~SharedMemoryFactoryProxy() override;
|
||||
|
||||
// Forwards CreateSharedMemory() calls to |factory_|. Users should always call
|
||||
// this function in one thread. Users should not call this function after the
|
||||
// SharedMemoryFactory which current instance created from has been destroyed.
|
||||
std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override;
|
||||
|
||||
private:
|
||||
explicit SharedMemoryFactoryProxy(SharedMemoryFactory* factory);
|
||||
|
||||
SharedMemoryFactory* factory_ = nullptr;
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
SharedMemoryFactoryProxy::SharedMemoryFactoryProxy(
|
||||
SharedMemoryFactory* factory) {
|
||||
RTC_DCHECK(factory);
|
||||
factory_ = factory;
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<SharedMemoryFactory>
|
||||
SharedMemoryFactoryProxy::Create(SharedMemoryFactory* factory) {
|
||||
return std::unique_ptr<SharedMemoryFactory>(
|
||||
new SharedMemoryFactoryProxy(factory));
|
||||
}
|
||||
|
||||
SharedMemoryFactoryProxy::~SharedMemoryFactoryProxy() = default;
|
||||
|
||||
std::unique_ptr<SharedMemory>
|
||||
SharedMemoryFactoryProxy::CreateSharedMemory(size_t size) {
|
||||
RTC_DCHECK(thread_checker_.CalledOnValidThread());
|
||||
return factory_->CreateSharedMemory(size);
|
||||
}
|
||||
|
||||
FallbackDesktopCapturerWrapper::FallbackDesktopCapturerWrapper(
|
||||
std::unique_ptr<DesktopCapturer> main_capturer,
|
||||
std::unique_ptr<DesktopCapturer> secondary_capturer)
|
||||
: main_capturer_(std::move(main_capturer)),
|
||||
secondary_capturer_(std::move(secondary_capturer)) {
|
||||
RTC_DCHECK(main_capturer_);
|
||||
RTC_DCHECK(secondary_capturer_);
|
||||
}
|
||||
|
||||
FallbackDesktopCapturerWrapper::~FallbackDesktopCapturerWrapper() = default;
|
||||
|
||||
void FallbackDesktopCapturerWrapper::Start(
|
||||
DesktopCapturer::Callback* callback) {
|
||||
// FallbackDesktopCapturerWrapper catchs the callback of the main capturer,
|
||||
// and checks its return value to decide whether the secondary capturer should
|
||||
// be involved.
|
||||
main_capturer_->Start(this);
|
||||
// For the secondary capturer, we do not have a backup plan anymore, so
|
||||
// FallbackDesktopCapturerWrapper won't check its return value any more. It
|
||||
// will directly return to the input |callback|.
|
||||
secondary_capturer_->Start(callback);
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
void FallbackDesktopCapturerWrapper::SetSharedMemoryFactory(
|
||||
std::unique_ptr<SharedMemoryFactory> shared_memory_factory) {
|
||||
shared_memory_factory_ = std::move(shared_memory_factory);
|
||||
if (shared_memory_factory_) {
|
||||
main_capturer_->SetSharedMemoryFactory(
|
||||
SharedMemoryFactoryProxy::Create(shared_memory_factory_.get()));
|
||||
secondary_capturer_->SetSharedMemoryFactory(
|
||||
SharedMemoryFactoryProxy::Create(shared_memory_factory_.get()));
|
||||
} else {
|
||||
main_capturer_->SetSharedMemoryFactory(
|
||||
std::unique_ptr<SharedMemoryFactory>());
|
||||
secondary_capturer_->SetSharedMemoryFactory(
|
||||
std::unique_ptr<SharedMemoryFactory>());
|
||||
}
|
||||
}
|
||||
|
||||
void FallbackDesktopCapturerWrapper::CaptureFrame() {
|
||||
RTC_DCHECK(callback_);
|
||||
if (main_capturer_permanent_error_) {
|
||||
secondary_capturer_->CaptureFrame();
|
||||
} else {
|
||||
main_capturer_->CaptureFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void FallbackDesktopCapturerWrapper::SetExcludedWindow(WindowId window) {
|
||||
main_capturer_->SetExcludedWindow(window);
|
||||
secondary_capturer_->SetExcludedWindow(window);
|
||||
}
|
||||
|
||||
bool FallbackDesktopCapturerWrapper::GetSourceList(SourceList* sources) {
|
||||
if (main_capturer_permanent_error_) {
|
||||
return secondary_capturer_->GetSourceList(sources);
|
||||
}
|
||||
return main_capturer_->GetSourceList(sources);
|
||||
}
|
||||
|
||||
bool FallbackDesktopCapturerWrapper::SelectSource(SourceId id) {
|
||||
if (main_capturer_permanent_error_) {
|
||||
return secondary_capturer_->SelectSource(id);
|
||||
}
|
||||
return main_capturer_->SelectSource(id) &&
|
||||
secondary_capturer_->SelectSource(id);
|
||||
}
|
||||
|
||||
bool FallbackDesktopCapturerWrapper::FocusOnSelectedSource() {
|
||||
if (main_capturer_permanent_error_) {
|
||||
return secondary_capturer_->FocusOnSelectedSource();
|
||||
}
|
||||
return main_capturer_->FocusOnSelectedSource() ||
|
||||
secondary_capturer_->FocusOnSelectedSource();
|
||||
}
|
||||
|
||||
void FallbackDesktopCapturerWrapper::OnCaptureResult(
|
||||
Result result,
|
||||
std::unique_ptr<DesktopFrame> frame) {
|
||||
RTC_DCHECK(callback_);
|
||||
if (result == Result::SUCCESS) {
|
||||
callback_->OnCaptureResult(result, std::move(frame));
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == Result::ERROR_PERMANENT) {
|
||||
main_capturer_permanent_error_ = true;
|
||||
}
|
||||
secondary_capturer_->CaptureFrame();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_FALLBACK_DESKTOP_CAPTURER_WRAPPER_H_
|
||||
#define WEBRTC_MODULES_DESKTOP_CAPTURE_FALLBACK_DESKTOP_CAPTURER_WRAPPER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "webrtc/modules/desktop_capture/desktop_capturer.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_capture_types.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_frame.h"
|
||||
#include "webrtc/modules/desktop_capture/shared_memory.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// A DesktopCapturer wrapper owns two DesktopCapturer implementations. If the
|
||||
// main DesktopCapturer fails, it uses the secondary one instead. Two capturers
|
||||
// are expected to return same SourceList, and the meaning of each SourceId is
|
||||
// identical, otherwise FallbackDesktopCapturerWrapper may return frames from
|
||||
// different sources. Using asynchronized DesktopCapturer implementations with
|
||||
// SharedMemoryFactory is not supported, and may result crash or assertion
|
||||
// failure.
|
||||
class FallbackDesktopCapturerWrapper final : public DesktopCapturer,
|
||||
public DesktopCapturer::Callback {
|
||||
public:
|
||||
FallbackDesktopCapturerWrapper(
|
||||
std::unique_ptr<DesktopCapturer> main_capturer,
|
||||
std::unique_ptr<DesktopCapturer> secondary_capturer);
|
||||
~FallbackDesktopCapturerWrapper() override;
|
||||
|
||||
// DesktopCapturer interface.
|
||||
void Start(DesktopCapturer::Callback* callback) override;
|
||||
void SetSharedMemoryFactory(
|
||||
std::unique_ptr<SharedMemoryFactory> shared_memory_factory) override;
|
||||
void CaptureFrame() override;
|
||||
void SetExcludedWindow(WindowId window) override;
|
||||
bool GetSourceList(SourceList* sources) override;
|
||||
bool SelectSource(SourceId id) override;
|
||||
bool FocusOnSelectedSource() override;
|
||||
|
||||
private:
|
||||
// DesktopCapturer::Callback interface.
|
||||
void OnCaptureResult(Result result,
|
||||
std::unique_ptr<DesktopFrame> frame) override;
|
||||
|
||||
const std::unique_ptr<DesktopCapturer> main_capturer_;
|
||||
const std::unique_ptr<DesktopCapturer> secondary_capturer_;
|
||||
std::unique_ptr<SharedMemoryFactory> shared_memory_factory_;
|
||||
bool main_capturer_permanent_error_ = false;
|
||||
DesktopCapturer::Callback* callback_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_FALLBACK_DESKTOP_CAPTURER_WRAPPER_H_
|
||||
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/desktop_capture/fallback_desktop_capturer_wrapper.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/modules/desktop_capture/desktop_capturer.h"
|
||||
#include "webrtc/modules/desktop_capture/desktop_frame_generator.h"
|
||||
#include "webrtc/modules/desktop_capture/fake_desktop_capturer.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<DesktopCapturer> CreateDesktopCapturer(
|
||||
PainterDesktopFrameGenerator* frame_generator) {
|
||||
std::unique_ptr<FakeDesktopCapturer> capturer(new FakeDesktopCapturer());
|
||||
capturer->set_frame_generator(frame_generator);
|
||||
return std::move(capturer);
|
||||
}
|
||||
|
||||
class FakeSharedMemory : public SharedMemory {
|
||||
public:
|
||||
explicit FakeSharedMemory(size_t size);
|
||||
~FakeSharedMemory() override;
|
||||
|
||||
private:
|
||||
static int next_id_;
|
||||
};
|
||||
|
||||
// static
|
||||
int FakeSharedMemory::next_id_ = 0;
|
||||
|
||||
FakeSharedMemory::FakeSharedMemory(size_t size)
|
||||
: SharedMemory(new char[size], size, 0, next_id_++) {}
|
||||
|
||||
FakeSharedMemory::~FakeSharedMemory() {
|
||||
delete[] static_cast<char*>(data_);
|
||||
}
|
||||
|
||||
class FakeSharedMemoryFactory : public SharedMemoryFactory {
|
||||
public:
|
||||
FakeSharedMemoryFactory() = default;
|
||||
~FakeSharedMemoryFactory() override = default;
|
||||
|
||||
std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override;
|
||||
};
|
||||
|
||||
std::unique_ptr<SharedMemory> FakeSharedMemoryFactory::CreateSharedMemory(
|
||||
size_t size) {
|
||||
return std::unique_ptr<SharedMemory>(new FakeSharedMemory(size));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class FallbackDesktopCapturerWrapperTest : public testing::Test,
|
||||
public DesktopCapturer::Callback {
|
||||
public:
|
||||
FallbackDesktopCapturerWrapperTest();
|
||||
~FallbackDesktopCapturerWrapperTest() override = default;
|
||||
|
||||
protected:
|
||||
std::vector<std::pair<DesktopCapturer::Result, bool>> results_;
|
||||
FakeDesktopCapturer* main_capturer_ = nullptr;
|
||||
FakeDesktopCapturer* secondary_capturer_ = nullptr;
|
||||
std::unique_ptr<FallbackDesktopCapturerWrapper> wrapper_;
|
||||
|
||||
private:
|
||||
// DesktopCapturer::Callback interface
|
||||
void OnCaptureResult(DesktopCapturer::Result result,
|
||||
std::unique_ptr<DesktopFrame> frame) override;
|
||||
PainterDesktopFrameGenerator frame_generator;
|
||||
};
|
||||
|
||||
FallbackDesktopCapturerWrapperTest::FallbackDesktopCapturerWrapperTest() {
|
||||
frame_generator.size()->set(1024, 768);
|
||||
std::unique_ptr<DesktopCapturer> main_capturer =
|
||||
CreateDesktopCapturer(&frame_generator);
|
||||
std::unique_ptr<DesktopCapturer> secondary_capturer =
|
||||
CreateDesktopCapturer(&frame_generator);
|
||||
main_capturer_ = static_cast<FakeDesktopCapturer*>(main_capturer.get());
|
||||
secondary_capturer_ =
|
||||
static_cast<FakeDesktopCapturer*>(secondary_capturer.get());
|
||||
wrapper_.reset(new FallbackDesktopCapturerWrapper(
|
||||
std::move(main_capturer), std::move(secondary_capturer)));
|
||||
wrapper_->Start(this);
|
||||
}
|
||||
|
||||
void FallbackDesktopCapturerWrapperTest::OnCaptureResult(
|
||||
DesktopCapturer::Result result,
|
||||
std::unique_ptr<DesktopFrame> frame) {
|
||||
results_.emplace_back(result, !!frame);
|
||||
}
|
||||
|
||||
TEST_F(FallbackDesktopCapturerWrapperTest, MainNeverFailed) {
|
||||
wrapper_->CaptureFrame();
|
||||
ASSERT_EQ(main_capturer_->num_capture_attempts(), 1);
|
||||
ASSERT_EQ(main_capturer_->num_frames_captured(), 1);
|
||||
ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 0);
|
||||
ASSERT_EQ(secondary_capturer_->num_frames_captured(), 0);
|
||||
ASSERT_EQ(results_.size(), 1U);
|
||||
ASSERT_EQ(results_[0],
|
||||
std::make_pair(DesktopCapturer::Result::SUCCESS, true));
|
||||
}
|
||||
|
||||
TEST_F(FallbackDesktopCapturerWrapperTest, MainFailedTemporarily) {
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::ERROR_TEMPORARY);
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::SUCCESS);
|
||||
wrapper_->CaptureFrame();
|
||||
|
||||
ASSERT_EQ(main_capturer_->num_capture_attempts(), 3);
|
||||
ASSERT_EQ(main_capturer_->num_frames_captured(), 2);
|
||||
ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 1);
|
||||
ASSERT_EQ(secondary_capturer_->num_frames_captured(), 1);
|
||||
ASSERT_EQ(results_.size(), 3U);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ASSERT_EQ(results_[i],
|
||||
std::make_pair(DesktopCapturer::Result::SUCCESS, true));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FallbackDesktopCapturerWrapperTest, MainFailedPermanently) {
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::ERROR_PERMANENT);
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::SUCCESS);
|
||||
wrapper_->CaptureFrame();
|
||||
|
||||
ASSERT_EQ(main_capturer_->num_capture_attempts(), 2);
|
||||
ASSERT_EQ(main_capturer_->num_frames_captured(), 1);
|
||||
ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 2);
|
||||
ASSERT_EQ(secondary_capturer_->num_frames_captured(), 2);
|
||||
ASSERT_EQ(results_.size(), 3U);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ASSERT_EQ(results_[i],
|
||||
std::make_pair(DesktopCapturer::Result::SUCCESS, true));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FallbackDesktopCapturerWrapperTest, BothFailed) {
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::ERROR_PERMANENT);
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::SUCCESS);
|
||||
wrapper_->CaptureFrame();
|
||||
secondary_capturer_->set_result(DesktopCapturer::Result::ERROR_TEMPORARY);
|
||||
wrapper_->CaptureFrame();
|
||||
secondary_capturer_->set_result(DesktopCapturer::Result::ERROR_PERMANENT);
|
||||
wrapper_->CaptureFrame();
|
||||
wrapper_->CaptureFrame();
|
||||
|
||||
ASSERT_EQ(main_capturer_->num_capture_attempts(), 2);
|
||||
ASSERT_EQ(main_capturer_->num_frames_captured(), 1);
|
||||
ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 5);
|
||||
ASSERT_EQ(secondary_capturer_->num_frames_captured(), 2);
|
||||
ASSERT_EQ(results_.size(), 6U);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ASSERT_EQ(results_[i],
|
||||
std::make_pair(DesktopCapturer::Result::SUCCESS, true));
|
||||
}
|
||||
ASSERT_EQ(results_[3],
|
||||
std::make_pair(DesktopCapturer::Result::ERROR_TEMPORARY, false));
|
||||
ASSERT_EQ(results_[4],
|
||||
std::make_pair(DesktopCapturer::Result::ERROR_PERMANENT, false));
|
||||
ASSERT_EQ(results_[5],
|
||||
std::make_pair(DesktopCapturer::Result::ERROR_PERMANENT, false));
|
||||
}
|
||||
|
||||
TEST_F(FallbackDesktopCapturerWrapperTest, WithSharedMemory) {
|
||||
wrapper_->SetSharedMemoryFactory(std::unique_ptr<SharedMemoryFactory>(
|
||||
new FakeSharedMemoryFactory()));
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::ERROR_TEMPORARY);
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::SUCCESS);
|
||||
wrapper_->CaptureFrame();
|
||||
main_capturer_->set_result(DesktopCapturer::Result::ERROR_PERMANENT);
|
||||
wrapper_->CaptureFrame();
|
||||
wrapper_->CaptureFrame();
|
||||
|
||||
ASSERT_EQ(main_capturer_->num_capture_attempts(), 4);
|
||||
ASSERT_EQ(main_capturer_->num_frames_captured(), 2);
|
||||
ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 3);
|
||||
ASSERT_EQ(secondary_capturer_->num_frames_captured(), 3);
|
||||
ASSERT_EQ(results_.size(), 5U);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ASSERT_EQ(results_[i],
|
||||
std::make_pair(DesktopCapturer::Result::SUCCESS, true));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -20,6 +20,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user