Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,5 @@
include_rules = [
# Allow include of sdk/android to allow accessing the JVM and Env in tests.
"+sdk/android",
"+modules/utility/include/jvm_android.h",
]

View file

@ -0,0 +1,51 @@
/*
* Copyright 2015 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 "pc/test/android_test_initializer.h"
#include <jni.h>
#include <pthread.h>
#include <stddef.h>
#include "modules/utility/include/jvm_android.h"
#include "rtc_base/checks.h"
#include "sdk/android/src/jni/jvm.h"
// TODO(phoglund): This include is to a target we can't really depend on.
// We need to either break it out into a smaller target or find some way to
// not use it.
#include "rtc_base/ssl_adapter.h"
namespace webrtc {
namespace {
static pthread_once_t g_initialize_once = PTHREAD_ONCE_INIT;
// There can only be one JNI_OnLoad in each binary. So since this is a GTEST
// C++ runner binary, we want to initialize the same global objects we normally
// do if this had been a Java binary.
void EnsureInitializedOnce() {
RTC_CHECK(::webrtc::jni::GetJVM() != nullptr);
JNIEnv* jni = ::webrtc::jni::AttachCurrentThreadIfNeeded();
JavaVM* jvm = NULL;
RTC_CHECK_EQ(0, jni->GetJavaVM(&jvm));
RTC_CHECK(rtc::InitializeSSL()) << "Failed to InitializeSSL()";
JVM::Initialize(jvm);
}
} // anonymous namespace
void InitializeAndroidObjects() {
RTC_CHECK_EQ(0, pthread_once(&g_initialize_once, &EnsureInitializedOnce));
}
} // namespace webrtc

View file

@ -0,0 +1,20 @@
/*
* Copyright 2015 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 PC_TEST_ANDROID_TEST_INITIALIZER_H_
#define PC_TEST_ANDROID_TEST_INITIALIZER_H_
namespace webrtc {
void InitializeAndroidObjects();
} // namespace webrtc
#endif // PC_TEST_ANDROID_TEST_INITIALIZER_H_

View file

@ -0,0 +1,63 @@
/*
* Copyright 2023 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 "pc/test/enable_fake_media.h"
#include <memory>
#include <utility>
#include "absl/base/nullability.h"
#include "api/environment/environment.h"
#include "api/peer_connection_interface.h"
#include "call/call.h"
#include "call/call_config.h"
#include "media/base/fake_media_engine.h"
#include "pc/media_factory.h"
#include "rtc_base/checks.h"
namespace webrtc {
using ::cricket::FakeMediaEngine;
using ::cricket::MediaEngineInterface;
void EnableFakeMedia(
PeerConnectionFactoryDependencies& deps,
absl::Nonnull<std::unique_ptr<FakeMediaEngine>> fake_media_engine) {
class FakeMediaFactory : public MediaFactory {
public:
explicit FakeMediaFactory(
absl::Nonnull<std::unique_ptr<FakeMediaEngine>> fake)
: fake_(std::move(fake)) {}
std::unique_ptr<Call> CreateCall(const CallConfig& config) override {
return Call::Create(config);
}
std::unique_ptr<MediaEngineInterface> CreateMediaEngine(
const Environment& /*env*/,
PeerConnectionFactoryDependencies& /*dependencies*/) {
RTC_CHECK(fake_ != nullptr)
<< "CreateMediaEngine can be called at most once.";
return std::move(fake_);
}
private:
absl::Nullable<std::unique_ptr<FakeMediaEngine>> fake_;
};
deps.media_factory =
std::make_unique<FakeMediaFactory>(std::move(fake_media_engine));
}
void EnableFakeMedia(PeerConnectionFactoryDependencies& deps) {
EnableFakeMedia(deps, std::make_unique<cricket::FakeMediaEngine>());
}
} // namespace webrtc

View file

@ -0,0 +1,38 @@
/*
* Copyright 2023 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.
*/
// Enables fake media support for PeerConnnectionFactory created from `deps` for
// testing purposes. Such fake media support ignores media dependencies in the
// `PeerConnectionFactoryDependencies`. Allows to test PeerConnection and
// PeerConnectionFactory in the presence of the media, but doesn't test media
// support itself.
#ifndef PC_TEST_ENABLE_FAKE_MEDIA_H_
#define PC_TEST_ENABLE_FAKE_MEDIA_H_
#include <memory>
#include "absl/base/nullability.h"
#include "api/peer_connection_interface.h"
#include "media/base/fake_media_engine.h"
namespace webrtc {
// Enables media support backed by the 'fake_media_engine'.
void EnableFakeMedia(
PeerConnectionFactoryDependencies& deps,
absl::Nonnull<std::unique_ptr<cricket::FakeMediaEngine>> fake_media_engine);
// Enables media support backed by unspecified lightweight fake implementation.
void EnableFakeMedia(PeerConnectionFactoryDependencies& deps);
} // namespace webrtc
#endif // PC_TEST_ENABLE_FAKE_MEDIA_H_

View file

@ -0,0 +1,519 @@
/*
* Copyright 2012 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 "pc/test/fake_audio_capture_module.h"
#include <string.h>
#include "api/make_ref_counted.h"
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/thread.h"
#include "rtc_base/time_utils.h"
using ::webrtc::TimeDelta;
// Audio sample value that is high enough that it doesn't occur naturally when
// frames are being faked. E.g. NetEq will not generate this large sample value
// unless it has received an audio frame containing a sample of this value.
// Even simpler buffers would likely just contain audio sample values of 0.
static const int kHighSampleValue = 10000;
// Constants here are derived by running VoE using a real ADM.
// The constants correspond to 10ms of mono audio at 44kHz.
static const int kTimePerFrameMs = 10;
static const uint8_t kNumberOfChannels = 1;
static const int kSamplesPerSecond = 44000;
static const int kTotalDelayMs = 0;
static const int kClockDriftMs = 0;
static const uint32_t kMaxVolume = 14392;
FakeAudioCaptureModule::FakeAudioCaptureModule()
: audio_callback_(nullptr),
recording_(false),
playing_(false),
play_is_initialized_(false),
rec_is_initialized_(false),
current_mic_level_(kMaxVolume),
started_(false),
next_frame_time_(0),
frames_received_(0) {}
FakeAudioCaptureModule::~FakeAudioCaptureModule() {
if (process_thread_) {
process_thread_->Stop();
}
}
rtc::scoped_refptr<FakeAudioCaptureModule> FakeAudioCaptureModule::Create() {
auto capture_module = rtc::make_ref_counted<FakeAudioCaptureModule>();
if (!capture_module->Initialize()) {
return nullptr;
}
return capture_module;
}
int FakeAudioCaptureModule::frames_received() const {
webrtc::MutexLock lock(&mutex_);
return frames_received_;
}
int32_t FakeAudioCaptureModule::ActiveAudioLayer(
AudioLayer* /*audio_layer*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::RegisterAudioCallback(
webrtc::AudioTransport* audio_callback) {
webrtc::MutexLock lock(&mutex_);
audio_callback_ = audio_callback;
return 0;
}
int32_t FakeAudioCaptureModule::Init() {
// Initialize is called by the factory method. Safe to ignore this Init call.
return 0;
}
int32_t FakeAudioCaptureModule::Terminate() {
// Clean up in the destructor. No action here, just success.
return 0;
}
bool FakeAudioCaptureModule::Initialized() const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int16_t FakeAudioCaptureModule::PlayoutDevices() {
RTC_DCHECK_NOTREACHED();
return 0;
}
int16_t FakeAudioCaptureModule::RecordingDevices() {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::PlayoutDeviceName(
uint16_t /*index*/,
char /*name*/[webrtc::kAdmMaxDeviceNameSize],
char /*guid*/[webrtc::kAdmMaxGuidSize]) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::RecordingDeviceName(
uint16_t /*index*/,
char /*name*/[webrtc::kAdmMaxDeviceNameSize],
char /*guid*/[webrtc::kAdmMaxGuidSize]) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SetPlayoutDevice(uint16_t /*index*/) {
// No playout device, just playing from file. Return success.
return 0;
}
int32_t FakeAudioCaptureModule::SetPlayoutDevice(WindowsDeviceType /*device*/) {
if (play_is_initialized_) {
return -1;
}
return 0;
}
int32_t FakeAudioCaptureModule::SetRecordingDevice(uint16_t /*index*/) {
// No recording device, just dropping audio. Return success.
return 0;
}
int32_t FakeAudioCaptureModule::SetRecordingDevice(
WindowsDeviceType /*device*/) {
if (rec_is_initialized_) {
return -1;
}
return 0;
}
int32_t FakeAudioCaptureModule::PlayoutIsAvailable(bool* /*available*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::InitPlayout() {
play_is_initialized_ = true;
return 0;
}
bool FakeAudioCaptureModule::PlayoutIsInitialized() const {
return play_is_initialized_;
}
int32_t FakeAudioCaptureModule::RecordingIsAvailable(bool* /*available*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::InitRecording() {
rec_is_initialized_ = true;
return 0;
}
bool FakeAudioCaptureModule::RecordingIsInitialized() const {
return rec_is_initialized_;
}
int32_t FakeAudioCaptureModule::StartPlayout() {
if (!play_is_initialized_) {
return -1;
}
{
webrtc::MutexLock lock(&mutex_);
playing_ = true;
}
bool start = true;
UpdateProcessing(start);
return 0;
}
int32_t FakeAudioCaptureModule::StopPlayout() {
bool start = false;
{
webrtc::MutexLock lock(&mutex_);
playing_ = false;
start = ShouldStartProcessing();
}
UpdateProcessing(start);
return 0;
}
bool FakeAudioCaptureModule::Playing() const {
webrtc::MutexLock lock(&mutex_);
return playing_;
}
int32_t FakeAudioCaptureModule::StartRecording() {
if (!rec_is_initialized_) {
return -1;
}
{
webrtc::MutexLock lock(&mutex_);
recording_ = true;
}
bool start = true;
UpdateProcessing(start);
return 0;
}
int32_t FakeAudioCaptureModule::StopRecording() {
bool start = false;
{
webrtc::MutexLock lock(&mutex_);
recording_ = false;
start = ShouldStartProcessing();
}
UpdateProcessing(start);
return 0;
}
bool FakeAudioCaptureModule::Recording() const {
webrtc::MutexLock lock(&mutex_);
return recording_;
}
int32_t FakeAudioCaptureModule::InitSpeaker() {
// No speaker, just playing from file. Return success.
return 0;
}
bool FakeAudioCaptureModule::SpeakerIsInitialized() const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::InitMicrophone() {
// No microphone, just playing from file. Return success.
return 0;
}
bool FakeAudioCaptureModule::MicrophoneIsInitialized() const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SpeakerVolumeIsAvailable(bool* /*available*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SetSpeakerVolume(uint32_t /*volume*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SpeakerVolume(uint32_t* /*volume*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::MaxSpeakerVolume(
uint32_t* /*max_volume*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::MinSpeakerVolume(
uint32_t* /*min_volume*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::MicrophoneVolumeIsAvailable(
bool* /*available*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
webrtc::MutexLock lock(&mutex_);
current_mic_level_ = volume;
return 0;
}
int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
webrtc::MutexLock lock(&mutex_);
*volume = current_mic_level_;
return 0;
}
int32_t FakeAudioCaptureModule::MaxMicrophoneVolume(
uint32_t* max_volume) const {
*max_volume = kMaxVolume;
return 0;
}
int32_t FakeAudioCaptureModule::MinMicrophoneVolume(
uint32_t* /*min_volume*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SpeakerMuteIsAvailable(bool* /*available*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SetSpeakerMute(bool /*enable*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SpeakerMute(bool* /*enabled*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::MicrophoneMuteIsAvailable(bool* /*available*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::SetMicrophoneMute(bool /*enable*/) {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::MicrophoneMute(bool* /*enabled*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::StereoPlayoutIsAvailable(
bool* available) const {
// No recording device, just dropping audio. Stereo can be dropped just
// as easily as mono.
*available = true;
return 0;
}
int32_t FakeAudioCaptureModule::SetStereoPlayout(bool /*enable*/) {
// No recording device, just dropping audio. Stereo can be dropped just
// as easily as mono.
return 0;
}
int32_t FakeAudioCaptureModule::StereoPlayout(bool* /*enabled*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::StereoRecordingIsAvailable(
bool* available) const {
// Keep thing simple. No stereo recording.
*available = false;
return 0;
}
int32_t FakeAudioCaptureModule::SetStereoRecording(bool enable) {
if (!enable) {
return 0;
}
return -1;
}
int32_t FakeAudioCaptureModule::StereoRecording(bool* /*enabled*/) const {
RTC_DCHECK_NOTREACHED();
return 0;
}
int32_t FakeAudioCaptureModule::PlayoutDelay(uint16_t* delay_ms) const {
// No delay since audio frames are dropped.
*delay_ms = 0;
return 0;
}
bool FakeAudioCaptureModule::Initialize() {
// Set the send buffer samples high enough that it would not occur on the
// remote side unless a packet containing a sample of that magnitude has been
// sent to it. Note that the audio processing pipeline will likely distort the
// original signal.
SetSendBuffer(kHighSampleValue);
return true;
}
void FakeAudioCaptureModule::SetSendBuffer(int value) {
Sample* buffer_ptr = reinterpret_cast<Sample*>(send_buffer_);
const size_t buffer_size_in_samples =
sizeof(send_buffer_) / kNumberBytesPerSample;
for (size_t i = 0; i < buffer_size_in_samples; ++i) {
buffer_ptr[i] = value;
}
}
void FakeAudioCaptureModule::ResetRecBuffer() {
memset(rec_buffer_, 0, sizeof(rec_buffer_));
}
bool FakeAudioCaptureModule::CheckRecBuffer(int value) {
const Sample* buffer_ptr = reinterpret_cast<const Sample*>(rec_buffer_);
const size_t buffer_size_in_samples =
sizeof(rec_buffer_) / kNumberBytesPerSample;
for (size_t i = 0; i < buffer_size_in_samples; ++i) {
if (buffer_ptr[i] >= value)
return true;
}
return false;
}
bool FakeAudioCaptureModule::ShouldStartProcessing() {
return recording_ || playing_;
}
void FakeAudioCaptureModule::UpdateProcessing(bool start) {
if (start) {
if (!process_thread_) {
process_thread_ = rtc::Thread::Create();
process_thread_->Start();
}
process_thread_->PostTask([this] { StartProcessP(); });
} else {
if (process_thread_) {
process_thread_->Stop();
process_thread_.reset(nullptr);
process_thread_checker_.Detach();
}
webrtc::MutexLock lock(&mutex_);
started_ = false;
}
}
void FakeAudioCaptureModule::StartProcessP() {
RTC_DCHECK_RUN_ON(&process_thread_checker_);
{
webrtc::MutexLock lock(&mutex_);
if (started_) {
// Already started.
return;
}
}
ProcessFrameP();
}
void FakeAudioCaptureModule::ProcessFrameP() {
RTC_DCHECK_RUN_ON(&process_thread_checker_);
{
webrtc::MutexLock lock(&mutex_);
if (!started_) {
next_frame_time_ = rtc::TimeMillis();
started_ = true;
}
// Receive and send frames every kTimePerFrameMs.
if (playing_) {
ReceiveFrameP();
}
if (recording_) {
SendFrameP();
}
}
next_frame_time_ += kTimePerFrameMs;
const int64_t current_time = rtc::TimeMillis();
const int64_t wait_time =
(next_frame_time_ > current_time) ? next_frame_time_ - current_time : 0;
process_thread_->PostDelayedTask([this] { ProcessFrameP(); },
TimeDelta::Millis(wait_time));
}
void FakeAudioCaptureModule::ReceiveFrameP() {
RTC_DCHECK_RUN_ON(&process_thread_checker_);
if (!audio_callback_) {
return;
}
ResetRecBuffer();
size_t nSamplesOut = 0;
int64_t elapsed_time_ms = 0;
int64_t ntp_time_ms = 0;
if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
kNumberOfChannels, kSamplesPerSecond,
rec_buffer_, nSamplesOut,
&elapsed_time_ms, &ntp_time_ms) != 0) {
RTC_DCHECK_NOTREACHED();
}
RTC_CHECK(nSamplesOut == kNumberSamples);
// The SetBuffer() function ensures that after decoding, the audio buffer
// should contain samples of similar magnitude (there is likely to be some
// distortion due to the audio pipeline). If one sample is detected to
// have the same or greater magnitude somewhere in the frame, an actual frame
// has been received from the remote side (i.e. faked frames are not being
// pulled).
if (CheckRecBuffer(kHighSampleValue)) {
++frames_received_;
}
}
void FakeAudioCaptureModule::SendFrameP() {
RTC_DCHECK_RUN_ON(&process_thread_checker_);
if (!audio_callback_) {
return;
}
bool key_pressed = false;
uint32_t current_mic_level = current_mic_level_;
if (audio_callback_->RecordedDataIsAvailable(
send_buffer_, kNumberSamples, kNumberBytesPerSample,
kNumberOfChannels, kSamplesPerSecond, kTotalDelayMs, kClockDriftMs,
current_mic_level, key_pressed, current_mic_level) != 0) {
RTC_DCHECK_NOTREACHED();
}
current_mic_level_ = current_mic_level;
}

View file

@ -0,0 +1,236 @@
/*
* Copyright 2012 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.
*/
// This class implements an AudioCaptureModule that can be used to detect if
// audio is being received properly if it is fed by another AudioCaptureModule
// in some arbitrary audio pipeline where they are connected. It does not play
// out or record any audio so it does not need access to any hardware and can
// therefore be used in the gtest testing framework.
// Note P postfix of a function indicates that it should only be called by the
// processing thread.
#ifndef PC_TEST_FAKE_AUDIO_CAPTURE_MODULE_H_
#define PC_TEST_FAKE_AUDIO_CAPTURE_MODULE_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "api/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/audio_device/include/audio_device_defines.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
namespace rtc {
class Thread;
} // namespace rtc
class FakeAudioCaptureModule : public webrtc::AudioDeviceModule {
public:
typedef uint16_t Sample;
// The value for the following constants have been derived by running VoE
// using a real ADM. The constants correspond to 10ms of mono audio at 44kHz.
static const size_t kNumberSamples = 440;
static const size_t kNumberBytesPerSample = sizeof(Sample);
// Creates a FakeAudioCaptureModule or returns NULL on failure.
static rtc::scoped_refptr<FakeAudioCaptureModule> Create();
// Returns the number of frames that have been successfully pulled by the
// instance. Note that correctly detecting success can only be done if the
// pulled frame was generated/pushed from a FakeAudioCaptureModule.
int frames_received() const RTC_LOCKS_EXCLUDED(mutex_);
int32_t ActiveAudioLayer(AudioLayer* audio_layer) const override;
// Note: Calling this method from a callback may result in deadlock.
int32_t RegisterAudioCallback(webrtc::AudioTransport* audio_callback) override
RTC_LOCKS_EXCLUDED(mutex_);
int32_t Init() override;
int32_t Terminate() override;
bool Initialized() const override;
int16_t PlayoutDevices() override;
int16_t RecordingDevices() override;
int32_t PlayoutDeviceName(uint16_t index,
char name[webrtc::kAdmMaxDeviceNameSize],
char guid[webrtc::kAdmMaxGuidSize]) override;
int32_t RecordingDeviceName(uint16_t index,
char name[webrtc::kAdmMaxDeviceNameSize],
char guid[webrtc::kAdmMaxGuidSize]) override;
int32_t SetPlayoutDevice(uint16_t index) override;
int32_t SetPlayoutDevice(WindowsDeviceType device) override;
int32_t SetRecordingDevice(uint16_t index) override;
int32_t SetRecordingDevice(WindowsDeviceType device) override;
int32_t PlayoutIsAvailable(bool* available) override;
int32_t InitPlayout() override;
bool PlayoutIsInitialized() const override;
int32_t RecordingIsAvailable(bool* available) override;
int32_t InitRecording() override;
bool RecordingIsInitialized() const override;
int32_t StartPlayout() RTC_LOCKS_EXCLUDED(mutex_) override;
int32_t StopPlayout() RTC_LOCKS_EXCLUDED(mutex_) override;
bool Playing() const RTC_LOCKS_EXCLUDED(mutex_) override;
int32_t StartRecording() RTC_LOCKS_EXCLUDED(mutex_) override;
int32_t StopRecording() RTC_LOCKS_EXCLUDED(mutex_) override;
bool Recording() const RTC_LOCKS_EXCLUDED(mutex_) override;
int32_t InitSpeaker() override;
bool SpeakerIsInitialized() const override;
int32_t InitMicrophone() override;
bool MicrophoneIsInitialized() const override;
int32_t SpeakerVolumeIsAvailable(bool* available) override;
int32_t SetSpeakerVolume(uint32_t volume) override;
int32_t SpeakerVolume(uint32_t* volume) const override;
int32_t MaxSpeakerVolume(uint32_t* max_volume) const override;
int32_t MinSpeakerVolume(uint32_t* min_volume) const override;
int32_t MicrophoneVolumeIsAvailable(bool* available) override;
int32_t SetMicrophoneVolume(uint32_t volume)
RTC_LOCKS_EXCLUDED(mutex_) override;
int32_t MicrophoneVolume(uint32_t* volume) const
RTC_LOCKS_EXCLUDED(mutex_) override;
int32_t MaxMicrophoneVolume(uint32_t* max_volume) const override;
int32_t MinMicrophoneVolume(uint32_t* min_volume) const override;
int32_t SpeakerMuteIsAvailable(bool* available) override;
int32_t SetSpeakerMute(bool enable) override;
int32_t SpeakerMute(bool* enabled) const override;
int32_t MicrophoneMuteIsAvailable(bool* available) override;
int32_t SetMicrophoneMute(bool enable) override;
int32_t MicrophoneMute(bool* enabled) const override;
int32_t StereoPlayoutIsAvailable(bool* available) const override;
int32_t SetStereoPlayout(bool enable) override;
int32_t StereoPlayout(bool* enabled) const override;
int32_t StereoRecordingIsAvailable(bool* available) const override;
int32_t SetStereoRecording(bool enable) override;
int32_t StereoRecording(bool* enabled) const override;
int32_t PlayoutDelay(uint16_t* delay_ms) const override;
bool BuiltInAECIsAvailable() const override { return false; }
int32_t EnableBuiltInAEC(bool enable) override { return -1; }
bool BuiltInAGCIsAvailable() const override { return false; }
int32_t EnableBuiltInAGC(bool enable) override { return -1; }
bool BuiltInNSIsAvailable() const override { return false; }
int32_t EnableBuiltInNS(bool enable) override { return -1; }
int32_t GetPlayoutUnderrunCount() const override { return -1; }
absl::optional<webrtc::AudioDeviceModule::Stats> GetStats() const override {
return webrtc::AudioDeviceModule::Stats();
}
#if defined(WEBRTC_IOS)
int GetPlayoutAudioParameters(
webrtc::AudioParameters* params) const override {
return -1;
}
int GetRecordAudioParameters(webrtc::AudioParameters* params) const override {
return -1;
}
#endif // WEBRTC_IOS
// End of functions inherited from webrtc::AudioDeviceModule.
protected:
// The constructor is protected because the class needs to be created as a
// reference counted object (for memory managment reasons). It could be
// exposed in which case the burden of proper instantiation would be put on
// the creator of a FakeAudioCaptureModule instance. To create an instance of
// this class use the Create(..) API.
FakeAudioCaptureModule();
// The destructor is protected because it is reference counted and should not
// be deleted directly.
virtual ~FakeAudioCaptureModule();
private:
// Initializes the state of the FakeAudioCaptureModule. This API is called on
// creation by the Create() API.
bool Initialize();
// SetBuffer() sets all samples in send_buffer_ to `value`.
void SetSendBuffer(int value);
// Resets rec_buffer_. I.e., sets all rec_buffer_ samples to 0.
void ResetRecBuffer();
// Returns true if rec_buffer_ contains one or more sample greater than or
// equal to `value`.
bool CheckRecBuffer(int value);
// Returns true/false depending on if recording or playback has been
// enabled/started.
bool ShouldStartProcessing() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Starts or stops the pushing and pulling of audio frames.
void UpdateProcessing(bool start) RTC_LOCKS_EXCLUDED(mutex_);
// Starts the periodic calling of ProcessFrame() in a thread safe way.
void StartProcessP();
// Periodcally called function that ensures that frames are pulled and pushed
// periodically if enabled/started.
void ProcessFrameP() RTC_LOCKS_EXCLUDED(mutex_);
// Pulls frames from the registered webrtc::AudioTransport.
void ReceiveFrameP() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Pushes frames to the registered webrtc::AudioTransport.
void SendFrameP() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Callback for playout and recording.
webrtc::AudioTransport* audio_callback_ RTC_GUARDED_BY(mutex_);
bool recording_ RTC_GUARDED_BY(
mutex_); // True when audio is being pushed from the instance.
bool playing_ RTC_GUARDED_BY(
mutex_); // True when audio is being pulled by the instance.
bool play_is_initialized_; // True when the instance is ready to pull audio.
bool rec_is_initialized_; // True when the instance is ready to push audio.
// Input to and output from RecordedDataIsAvailable(..) makes it possible to
// modify the current mic level. The implementation does not care about the
// mic level so it just feeds back what it receives.
uint32_t current_mic_level_ RTC_GUARDED_BY(mutex_);
// next_frame_time_ is updated in a non-drifting manner to indicate the next
// wall clock time the next frame should be generated and received. started_
// ensures that next_frame_time_ can be initialized properly on first call.
bool started_ RTC_GUARDED_BY(mutex_);
int64_t next_frame_time_ RTC_GUARDED_BY(process_thread_checker_);
std::unique_ptr<rtc::Thread> process_thread_;
// Buffer for storing samples received from the webrtc::AudioTransport.
char rec_buffer_[kNumberSamples * kNumberBytesPerSample];
// Buffer for samples to send to the webrtc::AudioTransport.
char send_buffer_[kNumberSamples * kNumberBytesPerSample];
// Counter of frames received that have samples of high enough amplitude to
// indicate that the frames are not faked somewhere in the audio pipeline
// (e.g. by a jitter buffer).
int frames_received_;
// Protects variables that are accessed from process_thread_ and
// the main thread.
mutable webrtc::Mutex mutex_;
webrtc::SequenceChecker process_thread_checker_{
webrtc::SequenceChecker::kDetached};
};
#endif // PC_TEST_FAKE_AUDIO_CAPTURE_MODULE_H_

View file

@ -0,0 +1,198 @@
/*
* Copyright 2012 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 "pc/test/fake_audio_capture_module.h"
#include <string.h>
#include <algorithm>
#include "api/scoped_refptr.h"
#include "rtc_base/gunit.h"
#include "rtc_base/synchronization/mutex.h"
#include "test/gtest.h"
class FakeAdmTest : public ::testing::Test, public webrtc::AudioTransport {
protected:
static const int kMsInSecond = 1000;
FakeAdmTest()
: push_iterations_(0), pull_iterations_(0), rec_buffer_bytes_(0) {
memset(rec_buffer_, 0, sizeof(rec_buffer_));
}
void SetUp() override {
fake_audio_capture_module_ = FakeAudioCaptureModule::Create();
EXPECT_TRUE(fake_audio_capture_module_.get() != NULL);
}
// Callbacks inherited from webrtc::AudioTransport.
// ADM is pushing data.
int32_t RecordedDataIsAvailable(const void* audioSamples,
const size_t nSamples,
const size_t nBytesPerSample,
const size_t nChannels,
const uint32_t samplesPerSec,
const uint32_t totalDelayMS,
const int32_t clockDrift,
const uint32_t currentMicLevel,
const bool keyPressed,
uint32_t& newMicLevel) override {
webrtc::MutexLock lock(&mutex_);
rec_buffer_bytes_ = nSamples * nBytesPerSample;
if ((rec_buffer_bytes_ == 0) ||
(rec_buffer_bytes_ >
FakeAudioCaptureModule::kNumberSamples *
FakeAudioCaptureModule::kNumberBytesPerSample)) {
ADD_FAILURE();
return -1;
}
memcpy(rec_buffer_, audioSamples, rec_buffer_bytes_);
++push_iterations_;
newMicLevel = currentMicLevel;
return 0;
}
void PullRenderData(int bits_per_sample,
int sample_rate,
size_t number_of_channels,
size_t number_of_frames,
void* audio_data,
int64_t* elapsed_time_ms,
int64_t* ntp_time_ms) override {}
// ADM is pulling data.
int32_t NeedMorePlayData(const size_t nSamples,
const size_t nBytesPerSample,
const size_t nChannels,
const uint32_t samplesPerSec,
void* audioSamples,
size_t& nSamplesOut,
int64_t* elapsed_time_ms,
int64_t* ntp_time_ms) override {
webrtc::MutexLock lock(&mutex_);
++pull_iterations_;
const size_t audio_buffer_size = nSamples * nBytesPerSample;
const size_t bytes_out =
RecordedDataReceived()
? CopyFromRecBuffer(audioSamples, audio_buffer_size)
: GenerateZeroBuffer(audioSamples, audio_buffer_size);
nSamplesOut = bytes_out / nBytesPerSample;
*elapsed_time_ms = 0;
*ntp_time_ms = 0;
return 0;
}
int push_iterations() const {
webrtc::MutexLock lock(&mutex_);
return push_iterations_;
}
int pull_iterations() const {
webrtc::MutexLock lock(&mutex_);
return pull_iterations_;
}
rtc::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module_;
private:
bool RecordedDataReceived() const { return rec_buffer_bytes_ != 0; }
size_t GenerateZeroBuffer(void* audio_buffer, size_t audio_buffer_size) {
memset(audio_buffer, 0, audio_buffer_size);
return audio_buffer_size;
}
size_t CopyFromRecBuffer(void* audio_buffer, size_t audio_buffer_size) {
EXPECT_EQ(audio_buffer_size, rec_buffer_bytes_);
const size_t min_buffer_size =
std::min(audio_buffer_size, rec_buffer_bytes_);
memcpy(audio_buffer, rec_buffer_, min_buffer_size);
return min_buffer_size;
}
rtc::AutoThread main_thread_;
mutable webrtc::Mutex mutex_;
int push_iterations_;
int pull_iterations_;
char rec_buffer_[FakeAudioCaptureModule::kNumberSamples *
FakeAudioCaptureModule::kNumberBytesPerSample];
size_t rec_buffer_bytes_;
};
TEST_F(FakeAdmTest, PlayoutTest) {
EXPECT_EQ(0, fake_audio_capture_module_->RegisterAudioCallback(this));
bool stereo_available = false;
EXPECT_EQ(0, fake_audio_capture_module_->StereoPlayoutIsAvailable(
&stereo_available));
EXPECT_TRUE(stereo_available);
EXPECT_NE(0, fake_audio_capture_module_->StartPlayout());
EXPECT_FALSE(fake_audio_capture_module_->PlayoutIsInitialized());
EXPECT_FALSE(fake_audio_capture_module_->Playing());
EXPECT_EQ(0, fake_audio_capture_module_->StopPlayout());
EXPECT_EQ(0, fake_audio_capture_module_->InitPlayout());
EXPECT_TRUE(fake_audio_capture_module_->PlayoutIsInitialized());
EXPECT_FALSE(fake_audio_capture_module_->Playing());
EXPECT_EQ(0, fake_audio_capture_module_->StartPlayout());
EXPECT_TRUE(fake_audio_capture_module_->Playing());
uint16_t delay_ms = 10;
EXPECT_EQ(0, fake_audio_capture_module_->PlayoutDelay(&delay_ms));
EXPECT_EQ(0, delay_ms);
EXPECT_TRUE_WAIT(pull_iterations() > 0, kMsInSecond);
EXPECT_GE(0, push_iterations());
EXPECT_EQ(0, fake_audio_capture_module_->StopPlayout());
EXPECT_FALSE(fake_audio_capture_module_->Playing());
}
TEST_F(FakeAdmTest, RecordTest) {
EXPECT_EQ(0, fake_audio_capture_module_->RegisterAudioCallback(this));
bool stereo_available = false;
EXPECT_EQ(0, fake_audio_capture_module_->StereoRecordingIsAvailable(
&stereo_available));
EXPECT_FALSE(stereo_available);
EXPECT_NE(0, fake_audio_capture_module_->StartRecording());
EXPECT_FALSE(fake_audio_capture_module_->Recording());
EXPECT_EQ(0, fake_audio_capture_module_->StopRecording());
EXPECT_EQ(0, fake_audio_capture_module_->InitRecording());
EXPECT_EQ(0, fake_audio_capture_module_->StartRecording());
EXPECT_TRUE(fake_audio_capture_module_->Recording());
EXPECT_TRUE_WAIT(push_iterations() > 0, kMsInSecond);
EXPECT_GE(0, pull_iterations());
EXPECT_EQ(0, fake_audio_capture_module_->StopRecording());
EXPECT_FALSE(fake_audio_capture_module_->Recording());
}
TEST_F(FakeAdmTest, DuplexTest) {
EXPECT_EQ(0, fake_audio_capture_module_->RegisterAudioCallback(this));
EXPECT_EQ(0, fake_audio_capture_module_->InitPlayout());
EXPECT_EQ(0, fake_audio_capture_module_->StartPlayout());
EXPECT_EQ(0, fake_audio_capture_module_->InitRecording());
EXPECT_EQ(0, fake_audio_capture_module_->StartRecording());
EXPECT_TRUE_WAIT(push_iterations() > 0, kMsInSecond);
EXPECT_TRUE_WAIT(pull_iterations() > 0, kMsInSecond);
EXPECT_EQ(0, fake_audio_capture_module_->StopPlayout());
EXPECT_EQ(0, fake_audio_capture_module_->StopRecording());
}

View file

@ -0,0 +1,238 @@
/*
* Copyright 2013 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 PC_TEST_FAKE_DATA_CHANNEL_CONTROLLER_H_
#define PC_TEST_FAKE_DATA_CHANNEL_CONTROLLER_H_
#include <set>
#include <string>
#include <utility>
#include "pc/sctp_data_channel.h"
#include "rtc_base/checks.h"
#include "rtc_base/weak_ptr.h"
class FakeDataChannelController
: public webrtc::SctpDataChannelControllerInterface {
public:
explicit FakeDataChannelController(rtc::Thread* network_thread)
: signaling_thread_(rtc::Thread::Current()),
network_thread_(network_thread),
send_blocked_(false),
transport_available_(false),
ready_to_send_(false),
transport_error_(false) {}
~FakeDataChannelController() override {
network_thread_->BlockingCall([&] {
RTC_DCHECK_RUN_ON(network_thread_);
weak_factory_.InvalidateWeakPtrs();
});
}
rtc::WeakPtr<FakeDataChannelController> weak_ptr() {
RTC_DCHECK_RUN_ON(network_thread_);
return weak_factory_.GetWeakPtr();
}
rtc::scoped_refptr<webrtc::SctpDataChannel> CreateDataChannel(
absl::string_view label,
webrtc::InternalDataChannelInit init) {
rtc::scoped_refptr<webrtc::SctpDataChannel> channel =
network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
rtc::WeakPtr<FakeDataChannelController> my_weak_ptr = weak_ptr();
// Explicitly associate the weak ptr instance with the current thread
// to catch early any inappropriate referencing of it on the network
// thread.
RTC_CHECK(my_weak_ptr);
rtc::scoped_refptr<webrtc::SctpDataChannel> channel =
webrtc::SctpDataChannel::Create(
std::move(my_weak_ptr), std::string(label),
transport_available_, init, signaling_thread_,
network_thread_);
if (transport_available_ && channel->sid_n().HasValue()) {
AddSctpDataStream(channel->sid_n());
}
if (ready_to_send_) {
network_thread_->PostTask([channel = channel] {
if (channel->state() !=
webrtc::DataChannelInterface::DataState::kClosed) {
channel->OnTransportReady();
}
});
}
connected_channels_.insert(channel.get());
return channel;
});
return channel;
}
webrtc::RTCError SendData(webrtc::StreamId sid,
const webrtc::SendDataParams& params,
const rtc::CopyOnWriteBuffer& payload) override {
RTC_DCHECK_RUN_ON(network_thread_);
RTC_CHECK(ready_to_send_);
RTC_CHECK(transport_available_);
if (send_blocked_) {
return webrtc::RTCError(webrtc::RTCErrorType::RESOURCE_EXHAUSTED);
}
if (transport_error_) {
return webrtc::RTCError(webrtc::RTCErrorType::INTERNAL_ERROR);
}
last_sid_ = sid;
last_send_data_params_ = params;
return webrtc::RTCError::OK();
}
void AddSctpDataStream(webrtc::StreamId sid) override {
RTC_DCHECK_RUN_ON(network_thread_);
RTC_CHECK(sid.HasValue());
if (!transport_available_) {
return;
}
known_stream_ids_.insert(sid);
}
void RemoveSctpDataStream(webrtc::StreamId sid) override {
RTC_DCHECK_RUN_ON(network_thread_);
RTC_CHECK(sid.HasValue());
known_stream_ids_.erase(sid);
// Unlike the real SCTP transport, act like the closing procedure finished
// instantly.
auto it = absl::c_find_if(connected_channels_,
[&](const auto* c) { return c->sid_n() == sid; });
// This path mimics the DCC's OnChannelClosed handler since the FDCC
// (this class) doesn't have a transport that would do that.
if (it != connected_channels_.end())
(*it)->OnClosingProcedureComplete();
}
void OnChannelStateChanged(
webrtc::SctpDataChannel* data_channel,
webrtc::DataChannelInterface::DataState state) override {
RTC_DCHECK_RUN_ON(network_thread_);
if (state == webrtc::DataChannelInterface::DataState::kOpen) {
++channels_opened_;
} else if (state == webrtc::DataChannelInterface::DataState::kClosed) {
++channels_closed_;
connected_channels_.erase(data_channel);
}
}
// Set true to emulate the SCTP stream being blocked by congestion control.
void set_send_blocked(bool blocked) {
network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
send_blocked_ = blocked;
if (!blocked) {
RTC_CHECK(transport_available_);
// Make a copy since `connected_channels_` may change while
// OnTransportReady is called.
auto copy = connected_channels_;
for (webrtc::SctpDataChannel* ch : copy) {
ch->OnTransportReady();
}
}
});
}
// Set true to emulate the transport channel creation, e.g. after
// setLocalDescription/setRemoteDescription called with data content.
void set_transport_available(bool available) {
network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
transport_available_ = available;
});
}
// Set true to emulate the transport OnTransportReady signal when the
// transport becomes writable for the first time.
void set_ready_to_send(bool ready) {
network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
RTC_CHECK(transport_available_);
ready_to_send_ = ready;
if (ready) {
std::set<webrtc::SctpDataChannel*>::iterator it;
for (it = connected_channels_.begin(); it != connected_channels_.end();
++it) {
(*it)->OnTransportReady();
}
}
});
}
void set_transport_error() {
network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
transport_error_ = true;
});
}
int last_sid() const {
return network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
return last_sid_.stream_id_int();
});
}
webrtc::SendDataParams last_send_data_params() const {
return network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
return last_send_data_params_;
});
}
bool IsConnected(webrtc::SctpDataChannel* data_channel) const {
return network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
return connected_channels_.find(data_channel) !=
connected_channels_.end();
});
}
bool IsStreamAdded(webrtc::StreamId id) const {
return network_thread_->BlockingCall([&]() {
RTC_DCHECK_RUN_ON(network_thread_);
return known_stream_ids_.find(id) != known_stream_ids_.end();
});
}
int channels_opened() const {
RTC_DCHECK_RUN_ON(network_thread_);
return channels_opened_;
}
int channels_closed() const {
RTC_DCHECK_RUN_ON(network_thread_);
return channels_closed_;
}
private:
rtc::Thread* const signaling_thread_;
rtc::Thread* const network_thread_;
webrtc::StreamId last_sid_ RTC_GUARDED_BY(network_thread_);
webrtc::SendDataParams last_send_data_params_ RTC_GUARDED_BY(network_thread_);
bool send_blocked_ RTC_GUARDED_BY(network_thread_);
bool transport_available_ RTC_GUARDED_BY(network_thread_);
bool ready_to_send_ RTC_GUARDED_BY(network_thread_);
bool transport_error_ RTC_GUARDED_BY(network_thread_);
int channels_closed_ RTC_GUARDED_BY(network_thread_) = 0;
int channels_opened_ RTC_GUARDED_BY(network_thread_) = 0;
std::set<webrtc::SctpDataChannel*> connected_channels_
RTC_GUARDED_BY(network_thread_);
std::set<webrtc::StreamId> known_stream_ids_ RTC_GUARDED_BY(network_thread_);
rtc::WeakPtrFactory<FakeDataChannelController> weak_factory_
RTC_GUARDED_BY(network_thread_){this};
};
#endif // PC_TEST_FAKE_DATA_CHANNEL_CONTROLLER_H_

View file

@ -0,0 +1,374 @@
/*
* Copyright 2018 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 PC_TEST_FAKE_PEER_CONNECTION_BASE_H_
#define PC_TEST_FAKE_PEER_CONNECTION_BASE_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "absl/types/optional.h"
#include "api/field_trials_view.h"
#include "api/sctp_transport_interface.h"
#include "pc/peer_connection_internal.h"
#include "test/scoped_key_value_config.h"
namespace webrtc {
// Customized PeerConnection fakes can be created by subclassing
// FakePeerConnectionBase then overriding the interesting methods. This class
// takes care of providing default implementations for all the pure virtual
// functions specified in the interfaces.
class FakePeerConnectionBase : public PeerConnectionInternal {
public:
// PeerConnectionInterface implementation.
rtc::scoped_refptr<StreamCollectionInterface> local_streams() override {
return nullptr;
}
rtc::scoped_refptr<StreamCollectionInterface> remote_streams() override {
return nullptr;
}
bool AddStream(MediaStreamInterface* stream) override { return false; }
void RemoveStream(MediaStreamInterface* stream) override {}
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack(
rtc::scoped_refptr<MediaStreamTrackInterface> track,
const std::vector<std::string>& stream_ids) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
}
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack(
rtc::scoped_refptr<MediaStreamTrackInterface> track,
const std::vector<std::string>& stream_ids,
const std::vector<RtpEncodingParameters>& init_send_encodings) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
}
RTCError RemoveTrackOrError(
rtc::scoped_refptr<RtpSenderInterface> sender) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION);
}
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
rtc::scoped_refptr<MediaStreamTrackInterface> track) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
}
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
rtc::scoped_refptr<MediaStreamTrackInterface> track,
const RtpTransceiverInit& init) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
}
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
cricket::MediaType media_type) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
}
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
cricket::MediaType media_type,
const RtpTransceiverInit& init) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
}
rtc::scoped_refptr<RtpSenderInterface> CreateSender(
const std::string& kind,
const std::string& stream_id) override {
return nullptr;
}
std::vector<rtc::scoped_refptr<RtpSenderInterface>> GetSenders()
const override {
return {};
}
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
const override {
return {};
}
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> GetTransceivers()
const override {
return {};
}
bool GetStats(StatsObserver* observer,
MediaStreamTrackInterface* track,
StatsOutputLevel level) override {
return false;
}
void GetStats(RTCStatsCollectorCallback* callback) override {}
void GetStats(
rtc::scoped_refptr<RtpSenderInterface> selector,
rtc::scoped_refptr<RTCStatsCollectorCallback> callback) override {}
void GetStats(
rtc::scoped_refptr<RtpReceiverInterface> selector,
rtc::scoped_refptr<RTCStatsCollectorCallback> callback) override {}
void ClearStatsCache() override {}
rtc::scoped_refptr<SctpTransportInterface> GetSctpTransport() const {
return nullptr;
}
RTCErrorOr<rtc::scoped_refptr<DataChannelInterface>> CreateDataChannelOrError(
const std::string& label,
const DataChannelInit* config) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION,
"Fake function called");
}
const SessionDescriptionInterface* local_description() const override {
return nullptr;
}
const SessionDescriptionInterface* remote_description() const override {
return nullptr;
}
const SessionDescriptionInterface* current_local_description()
const override {
return nullptr;
}
const SessionDescriptionInterface* current_remote_description()
const override {
return nullptr;
}
const SessionDescriptionInterface* pending_local_description()
const override {
return nullptr;
}
const SessionDescriptionInterface* pending_remote_description()
const override {
return nullptr;
}
void RestartIce() override {}
void CreateOffer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions& options) override {}
void CreateAnswer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions& options) override {}
void SetLocalDescription(SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) override {}
void SetRemoteDescription(SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) override {}
void SetRemoteDescription(
std::unique_ptr<SessionDescriptionInterface> desc,
rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer)
override {}
RTCConfiguration GetConfiguration() override { return RTCConfiguration(); }
RTCError SetConfiguration(
const PeerConnectionInterface::RTCConfiguration& config) override {
return RTCError();
}
bool AddIceCandidate(const IceCandidateInterface* candidate) override {
return false;
}
bool RemoveIceCandidates(
const std::vector<cricket::Candidate>& candidates) override {
return false;
}
RTCError SetBitrate(const BitrateSettings& bitrate) override {
return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
}
void ReconfigureBandwidthEstimation(
const BandwidthEstimationSettings& settings) override {}
void SetAudioPlayout(bool playout) override {}
void SetAudioRecording(bool recording) override {}
rtc::scoped_refptr<DtlsTransportInterface> LookupDtlsTransportByMid(
const std::string& mid) {
return nullptr;
}
SignalingState signaling_state() override { return SignalingState::kStable; }
IceConnectionState ice_connection_state() override {
return IceConnectionState::kIceConnectionNew;
}
IceConnectionState standardized_ice_connection_state() override {
return IceConnectionState::kIceConnectionNew;
}
PeerConnectionState peer_connection_state() override {
return PeerConnectionState::kNew;
}
IceGatheringState ice_gathering_state() override {
return IceGatheringState::kIceGatheringNew;
}
absl::optional<bool> can_trickle_ice_candidates() { return absl::nullopt; }
bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
int64_t output_period_ms) override {
return false;
}
bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output) override {
return false;
}
void StopRtcEventLog() override {}
void Close() override {}
// PeerConnectionInternal implementation.
rtc::Thread* network_thread() const override { return nullptr; }
rtc::Thread* worker_thread() const override { return nullptr; }
rtc::Thread* signaling_thread() const override { return nullptr; }
std::string session_id() const override { return ""; }
bool initial_offerer() const override { return false; }
std::vector<
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
GetTransceiversInternal() const override {
return {};
}
absl::optional<std::string> sctp_transport_name() const override {
return absl::nullopt;
}
absl::optional<std::string> sctp_mid() const override {
return absl::nullopt;
}
std::map<std::string, cricket::TransportStats> GetTransportStatsByNames(
const std::set<std::string>& transport_names) override {
return {};
}
Call::Stats GetCallStats() override { return Call::Stats(); }
absl::optional<AudioDeviceModule::Stats> GetAudioDeviceStats() override {
return absl::nullopt;
}
bool GetLocalCertificate(
const std::string& transport_name,
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override {
return false;
}
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
const std::string& transport_name) override {
return nullptr;
}
bool IceRestartPending(const std::string& content_name) const override {
return false;
}
bool NeedsIceRestart(const std::string& content_name) const override {
return false;
}
bool GetSslRole(const std::string& content_name,
rtc::SSLRole* role) override {
return false;
}
const PeerConnectionInterface::RTCConfiguration* configuration()
const override {
return nullptr;
}
void ReportSdpBundleUsage(
const SessionDescriptionInterface& remote_description) override {}
PeerConnectionMessageHandler* message_handler() override { return nullptr; }
RtpTransmissionManager* rtp_manager() override { return nullptr; }
const RtpTransmissionManager* rtp_manager() const override { return nullptr; }
bool dtls_enabled() const override { return false; }
const PeerConnectionFactoryInterface::Options* options() const override {
return nullptr;
}
CryptoOptions GetCryptoOptions() override { return CryptoOptions(); }
JsepTransportController* transport_controller_s() override { return nullptr; }
JsepTransportController* transport_controller_n() override { return nullptr; }
DataChannelController* data_channel_controller() override { return nullptr; }
cricket::PortAllocator* port_allocator() override { return nullptr; }
LegacyStatsCollector* legacy_stats() override { return nullptr; }
PeerConnectionObserver* Observer() const override { return nullptr; }
absl::optional<rtc::SSLRole> GetSctpSslRole_n() override {
return absl::nullopt;
}
PeerConnectionInterface::IceConnectionState ice_connection_state_internal()
override {
return PeerConnectionInterface::IceConnectionState::kIceConnectionNew;
}
void SetIceConnectionState(
PeerConnectionInterface::IceConnectionState new_state) override {}
void NoteUsageEvent(UsageEvent event) override {}
bool IsClosed() const override { return false; }
bool IsUnifiedPlan() const override { return true; }
bool ValidateBundleSettings(
const cricket::SessionDescription* desc,
const std::map<std::string, const cricket::ContentGroup*>&
bundle_groups_by_mid) override {
return false;
}
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
cricket::MediaType media_type,
rtc::scoped_refptr<MediaStreamTrackInterface> track,
const RtpTransceiverInit& init,
bool fire_callback = true) override {
return RTCError(RTCErrorType::INTERNAL_ERROR, "");
}
void StartSctpTransport(int local_port,
int remote_port,
int max_message_size) override {}
void AddRemoteCandidate(const std::string& mid,
const cricket::Candidate& candidate) override {}
Call* call_ptr() override { return nullptr; }
bool SrtpRequired() const override { return false; }
bool CreateDataChannelTransport(absl::string_view mid) override {
return false;
}
void DestroyDataChannelTransport(RTCError error) override {}
const FieldTrialsView& trials() const override { return field_trials_; }
protected:
test::ScopedKeyValueConfig field_trials_;
};
} // namespace webrtc
#endif // PC_TEST_FAKE_PEER_CONNECTION_BASE_H_

View file

@ -0,0 +1,570 @@
/*
* Copyright 2018 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 PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_
#define PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "api/environment/environment_factory.h"
#include "media/base/media_channel.h"
#include "pc/channel.h"
#include "pc/stream_collection.h"
#include "pc/test/enable_fake_media.h"
#include "pc/test/fake_data_channel_controller.h"
#include "pc/test/fake_peer_connection_base.h"
namespace webrtc {
// Fake VoiceMediaChannel where the result of GetStats can be configured.
class FakeVoiceMediaSendChannelForStats
: public cricket::FakeVoiceMediaSendChannel {
public:
explicit FakeVoiceMediaSendChannelForStats(TaskQueueBase* network_thread)
: cricket::FakeVoiceMediaSendChannel(cricket::AudioOptions(),
network_thread) {}
void SetStats(const cricket::VoiceMediaInfo& voice_info) {
send_stats_ = cricket::VoiceMediaSendInfo();
send_stats_->senders = voice_info.senders;
send_stats_->send_codecs = voice_info.send_codecs;
}
// VoiceMediaChannel overrides.
bool GetStats(cricket::VoiceMediaSendInfo* info) override {
if (send_stats_) {
*info = *send_stats_;
return true;
}
return false;
}
private:
absl::optional<cricket::VoiceMediaSendInfo> send_stats_;
};
class FakeVoiceMediaReceiveChannelForStats
: public cricket::FakeVoiceMediaReceiveChannel {
public:
explicit FakeVoiceMediaReceiveChannelForStats(TaskQueueBase* network_thread)
: cricket::FakeVoiceMediaReceiveChannel(cricket::AudioOptions(),
network_thread) {}
void SetStats(const cricket::VoiceMediaInfo& voice_info) {
receive_stats_ = cricket::VoiceMediaReceiveInfo();
receive_stats_->receivers = voice_info.receivers;
receive_stats_->receive_codecs = voice_info.receive_codecs;
receive_stats_->device_underrun_count = voice_info.device_underrun_count;
}
// VoiceMediaChannel overrides.
bool GetStats(cricket::VoiceMediaReceiveInfo* info,
bool get_and_clear_legacy_stats) override {
if (receive_stats_) {
*info = *receive_stats_;
return true;
}
return false;
}
private:
absl::optional<cricket::VoiceMediaReceiveInfo> receive_stats_;
};
// Fake VideoMediaChannel where the result of GetStats can be configured.
class FakeVideoMediaSendChannelForStats
: public cricket::FakeVideoMediaSendChannel {
public:
explicit FakeVideoMediaSendChannelForStats(TaskQueueBase* network_thread)
: cricket::FakeVideoMediaSendChannel(cricket::VideoOptions(),
network_thread) {}
void SetStats(const cricket::VideoMediaInfo& video_info) {
send_stats_ = cricket::VideoMediaSendInfo();
send_stats_->senders = video_info.senders;
send_stats_->aggregated_senders = video_info.aggregated_senders;
send_stats_->send_codecs = video_info.send_codecs;
}
// VideoMediaChannel overrides.
bool GetStats(cricket::VideoMediaSendInfo* info) override {
if (send_stats_) {
*info = *send_stats_;
return true;
}
return false;
}
private:
absl::optional<cricket::VideoMediaSendInfo> send_stats_;
};
class FakeVideoMediaReceiveChannelForStats
: public cricket::FakeVideoMediaReceiveChannel {
public:
explicit FakeVideoMediaReceiveChannelForStats(TaskQueueBase* network_thread)
: cricket::FakeVideoMediaReceiveChannel(cricket::VideoOptions(),
network_thread) {}
void SetStats(const cricket::VideoMediaInfo& video_info) {
receive_stats_ = cricket::VideoMediaReceiveInfo();
receive_stats_->receivers = video_info.receivers;
receive_stats_->receive_codecs = video_info.receive_codecs;
}
// VideoMediaChannel overrides.
bool GetStats(cricket::VideoMediaReceiveInfo* info) override {
if (receive_stats_) {
*info = *receive_stats_;
return true;
}
return false;
}
private:
absl::optional<cricket::VideoMediaReceiveInfo> receive_stats_;
};
constexpr bool kDefaultRtcpMuxRequired = true;
constexpr bool kDefaultSrtpRequired = true;
class VoiceChannelForTesting : public cricket::VoiceChannel {
public:
VoiceChannelForTesting(
rtc::Thread* worker_thread,
rtc::Thread* network_thread,
rtc::Thread* signaling_thread,
std::unique_ptr<cricket::VoiceMediaSendChannelInterface> send_channel,
std::unique_ptr<cricket::VoiceMediaReceiveChannelInterface>
receive_channel,
const std::string& content_name,
bool srtp_required,
CryptoOptions crypto_options,
rtc::UniqueRandomIdGenerator* ssrc_generator,
std::string transport_name)
: VoiceChannel(worker_thread,
network_thread,
signaling_thread,
std::move(send_channel),
std::move(receive_channel),
content_name,
srtp_required,
std::move(crypto_options),
ssrc_generator),
test_transport_name_(std::move(transport_name)) {}
private:
absl::string_view transport_name() const override {
return test_transport_name_;
}
const std::string test_transport_name_;
};
class VideoChannelForTesting : public cricket::VideoChannel {
public:
VideoChannelForTesting(
rtc::Thread* worker_thread,
rtc::Thread* network_thread,
rtc::Thread* signaling_thread,
std::unique_ptr<cricket::VideoMediaSendChannelInterface> send_channel,
std::unique_ptr<cricket::VideoMediaReceiveChannelInterface>
receive_channel,
const std::string& content_name,
bool srtp_required,
CryptoOptions crypto_options,
rtc::UniqueRandomIdGenerator* ssrc_generator,
std::string transport_name)
: VideoChannel(worker_thread,
network_thread,
signaling_thread,
std::move(send_channel),
std::move(receive_channel),
content_name,
srtp_required,
std::move(crypto_options),
ssrc_generator),
test_transport_name_(std::move(transport_name)) {}
private:
absl::string_view transport_name() const override {
return test_transport_name_;
}
const std::string test_transport_name_;
};
// This class is intended to be fed into the StatsCollector and
// RTCStatsCollector so that the stats functionality can be unit tested.
// Individual tests can configure this fake as needed to simulate scenarios
// under which to test the stats collectors.
class FakePeerConnectionForStats : public FakePeerConnectionBase {
public:
// TODO(steveanton): Add support for specifying separate threads to test
// multi-threading correctness.
FakePeerConnectionForStats()
: network_thread_(rtc::Thread::Current()),
worker_thread_(rtc::Thread::Current()),
signaling_thread_(rtc::Thread::Current()),
// TODO(hta): remove separate thread variables and use context.
dependencies_(MakeDependencies()),
context_(
ConnectionContext::Create(CreateEnvironment(), &dependencies_)),
local_streams_(StreamCollection::Create()),
remote_streams_(StreamCollection::Create()),
data_channel_controller_(network_thread_) {}
~FakePeerConnectionForStats() {
for (auto transceiver : transceivers_) {
transceiver->internal()->ClearChannel();
}
}
static PeerConnectionFactoryDependencies MakeDependencies() {
PeerConnectionFactoryDependencies dependencies;
dependencies.network_thread = rtc::Thread::Current();
dependencies.worker_thread = rtc::Thread::Current();
dependencies.signaling_thread = rtc::Thread::Current();
EnableFakeMedia(dependencies);
return dependencies;
}
rtc::scoped_refptr<StreamCollection> mutable_local_streams() {
return local_streams_;
}
rtc::scoped_refptr<StreamCollection> mutable_remote_streams() {
return remote_streams_;
}
rtc::scoped_refptr<RtpSenderInterface> AddSender(
rtc::scoped_refptr<RtpSenderInternal> sender) {
// TODO(steveanton): Switch tests to use RtpTransceivers directly.
auto sender_proxy = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
signaling_thread_, sender);
GetOrCreateFirstTransceiverOfType(sender->media_type())
->internal()
->AddSender(sender_proxy);
return sender_proxy;
}
void RemoveSender(rtc::scoped_refptr<RtpSenderInterface> sender) {
GetOrCreateFirstTransceiverOfType(sender->media_type())
->internal()
->RemoveSender(sender.get());
}
rtc::scoped_refptr<RtpReceiverInterface> AddReceiver(
rtc::scoped_refptr<RtpReceiverInternal> receiver) {
// TODO(steveanton): Switch tests to use RtpTransceivers directly.
auto receiver_proxy =
RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
signaling_thread_, worker_thread_, receiver);
GetOrCreateFirstTransceiverOfType(receiver->media_type())
->internal()
->AddReceiver(receiver_proxy);
return receiver_proxy;
}
void RemoveReceiver(rtc::scoped_refptr<RtpReceiverInterface> receiver) {
GetOrCreateFirstTransceiverOfType(receiver->media_type())
->internal()
->RemoveReceiver(receiver.get());
}
std::pair<FakeVoiceMediaSendChannelForStats*,
FakeVoiceMediaReceiveChannelForStats*>
AddVoiceChannel(
const std::string& mid,
const std::string& transport_name,
cricket::VoiceMediaInfo initial_stats = cricket::VoiceMediaInfo()) {
auto voice_media_send_channel =
std::make_unique<FakeVoiceMediaSendChannelForStats>(network_thread_);
auto voice_media_receive_channel =
std::make_unique<FakeVoiceMediaReceiveChannelForStats>(network_thread_);
auto* voice_media_send_channel_ptr = voice_media_send_channel.get();
auto* voice_media_receive_channel_ptr = voice_media_receive_channel.get();
auto voice_channel = std::make_unique<VoiceChannelForTesting>(
worker_thread_, network_thread_, signaling_thread_,
std::move(voice_media_send_channel),
std::move(voice_media_receive_channel), mid, kDefaultSrtpRequired,
CryptoOptions(), context_->ssrc_generator(), transport_name);
auto transceiver =
GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_AUDIO)
->internal();
if (transceiver->channel()) {
// This transceiver already has a channel, create a new one.
transceiver =
CreateTransceiverOfType(cricket::MEDIA_TYPE_AUDIO)->internal();
}
RTC_DCHECK(!transceiver->channel());
transceiver->SetChannel(std::move(voice_channel),
[](const std::string&) { return nullptr; });
voice_media_send_channel_ptr->SetStats(initial_stats);
voice_media_receive_channel_ptr->SetStats(initial_stats);
return std::make_pair(voice_media_send_channel_ptr,
voice_media_receive_channel_ptr);
}
std::pair<FakeVideoMediaSendChannelForStats*,
FakeVideoMediaReceiveChannelForStats*>
AddVideoChannel(
const std::string& mid,
const std::string& transport_name,
cricket::VideoMediaInfo initial_stats = cricket::VideoMediaInfo()) {
auto video_media_send_channel =
std::make_unique<FakeVideoMediaSendChannelForStats>(network_thread_);
auto video_media_receive_channel =
std::make_unique<FakeVideoMediaReceiveChannelForStats>(network_thread_);
auto video_media_send_channel_ptr = video_media_send_channel.get();
auto video_media_receive_channel_ptr = video_media_receive_channel.get();
auto video_channel = std::make_unique<VideoChannelForTesting>(
worker_thread_, network_thread_, signaling_thread_,
std::move(video_media_send_channel),
std::move(video_media_receive_channel), mid, kDefaultSrtpRequired,
CryptoOptions(), context_->ssrc_generator(), transport_name);
auto transceiver =
GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_VIDEO)
->internal();
if (transceiver->channel()) {
// This transceiver already has a channel, create a new one.
transceiver =
CreateTransceiverOfType(cricket::MEDIA_TYPE_VIDEO)->internal();
}
RTC_DCHECK(!transceiver->channel());
transceiver->SetChannel(std::move(video_channel),
[](const std::string&) { return nullptr; });
video_media_send_channel_ptr->SetStats(initial_stats);
video_media_receive_channel_ptr->SetStats(initial_stats);
return std::make_pair(video_media_send_channel_ptr,
video_media_receive_channel_ptr);
}
void AddSctpDataChannel(const std::string& label) {
AddSctpDataChannel(label, InternalDataChannelInit());
}
void AddSctpDataChannel(const std::string& label,
const InternalDataChannelInit& init) {
// TODO(bugs.webrtc.org/11547): Supply a separate network thread.
AddSctpDataChannel(SctpDataChannel::Create(
data_channel_controller_.weak_ptr(), label, false, init,
rtc::Thread::Current(), rtc::Thread::Current()));
}
void AddSctpDataChannel(rtc::scoped_refptr<SctpDataChannel> data_channel) {
sctp_data_channels_.push_back(data_channel);
}
void SetTransportStats(const std::string& transport_name,
const cricket::TransportChannelStats& channel_stats) {
SetTransportStats(
transport_name,
std::vector<cricket::TransportChannelStats>{channel_stats});
}
void SetTransportStats(
const std::string& transport_name,
const std::vector<cricket::TransportChannelStats>& channel_stats_list) {
cricket::TransportStats transport_stats;
transport_stats.transport_name = transport_name;
transport_stats.channel_stats = channel_stats_list;
transport_stats_by_name_[transport_name] = transport_stats;
}
void SetCallStats(const Call::Stats& call_stats) { call_stats_ = call_stats; }
void SetAudioDeviceStats(
absl::optional<AudioDeviceModule::Stats> audio_device_stats) {
audio_device_stats_ = audio_device_stats;
}
void SetLocalCertificate(
const std::string& transport_name,
rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
local_certificates_by_transport_[transport_name] = certificate;
}
void SetRemoteCertChain(const std::string& transport_name,
std::unique_ptr<rtc::SSLCertChain> chain) {
remote_cert_chains_by_transport_[transport_name] = std::move(chain);
}
// PeerConnectionInterface overrides.
rtc::scoped_refptr<StreamCollectionInterface> local_streams() override {
return local_streams_;
}
rtc::scoped_refptr<StreamCollectionInterface> remote_streams() override {
return remote_streams_;
}
std::vector<rtc::scoped_refptr<RtpSenderInterface>> GetSenders()
const override {
std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders;
for (auto transceiver : transceivers_) {
for (auto sender : transceiver->internal()->senders()) {
senders.push_back(sender);
}
}
return senders;
}
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
const override {
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> receivers;
for (auto transceiver : transceivers_) {
for (auto receiver : transceiver->internal()->receivers()) {
receivers.push_back(receiver);
}
}
return receivers;
}
// PeerConnectionInternal overrides.
rtc::Thread* network_thread() const override { return network_thread_; }
rtc::Thread* worker_thread() const override { return worker_thread_; }
rtc::Thread* signaling_thread() const override { return signaling_thread_; }
std::vector<
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
GetTransceiversInternal() const override {
return transceivers_;
}
std::vector<DataChannelStats> GetDataChannelStats() const override {
RTC_DCHECK_RUN_ON(signaling_thread());
std::vector<DataChannelStats> stats;
for (const auto& channel : sctp_data_channels_)
stats.push_back(channel->GetStats());
return stats;
}
cricket::CandidateStatsList GetPooledCandidateStats() const override {
return {};
}
std::map<std::string, cricket::TransportStats> GetTransportStatsByNames(
const std::set<std::string>& transport_names) override {
RTC_DCHECK_RUN_ON(network_thread_);
std::map<std::string, cricket::TransportStats> transport_stats_by_name;
for (const std::string& transport_name : transport_names) {
transport_stats_by_name[transport_name] =
GetTransportStatsByName(transport_name);
}
return transport_stats_by_name;
}
Call::Stats GetCallStats() override { return call_stats_; }
absl::optional<AudioDeviceModule::Stats> GetAudioDeviceStats() override {
return audio_device_stats_;
}
bool GetLocalCertificate(
const std::string& transport_name,
rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override {
auto it = local_certificates_by_transport_.find(transport_name);
if (it != local_certificates_by_transport_.end()) {
*certificate = it->second;
return true;
} else {
return false;
}
}
std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
const std::string& transport_name) override {
auto it = remote_cert_chains_by_transport_.find(transport_name);
if (it != remote_cert_chains_by_transport_.end()) {
return it->second->Clone();
} else {
return nullptr;
}
}
private:
cricket::TransportStats GetTransportStatsByName(
const std::string& transport_name) {
auto it = transport_stats_by_name_.find(transport_name);
if (it != transport_stats_by_name_.end()) {
// If specific transport stats have been specified, return those.
return it->second;
}
// Otherwise, generate some dummy stats.
cricket::TransportChannelStats channel_stats;
channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
cricket::TransportStats transport_stats;
transport_stats.transport_name = transport_name;
transport_stats.channel_stats.push_back(channel_stats);
return transport_stats;
}
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
GetOrCreateFirstTransceiverOfType(cricket::MediaType media_type) {
for (auto transceiver : transceivers_) {
if (transceiver->internal()->media_type() == media_type) {
return transceiver;
}
}
return CreateTransceiverOfType(media_type);
}
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
CreateTransceiverOfType(cricket::MediaType media_type) {
auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
signaling_thread_,
rtc::make_ref_counted<RtpTransceiver>(media_type, context_.get()));
transceivers_.push_back(transceiver);
return transceiver;
}
rtc::Thread* const network_thread_;
rtc::Thread* const worker_thread_;
rtc::Thread* const signaling_thread_;
PeerConnectionFactoryDependencies dependencies_;
rtc::scoped_refptr<ConnectionContext> context_;
rtc::scoped_refptr<StreamCollection> local_streams_;
rtc::scoped_refptr<StreamCollection> remote_streams_;
std::vector<
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
transceivers_;
FakeDataChannelController data_channel_controller_;
std::vector<rtc::scoped_refptr<SctpDataChannel>> sctp_data_channels_;
std::map<std::string, cricket::TransportStats> transport_stats_by_name_;
Call::Stats call_stats_;
absl::optional<AudioDeviceModule::Stats> audio_device_stats_;
std::map<std::string, rtc::scoped_refptr<rtc::RTCCertificate>>
local_certificates_by_transport_;
std::map<std::string, std::unique_ptr<rtc::SSLCertChain>>
remote_cert_chains_by_transport_;
};
} // namespace webrtc
#endif // PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_

View file

@ -0,0 +1,103 @@
/*
* Copyright 2018 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 PC_TEST_FAKE_PERIODIC_VIDEO_SOURCE_H_
#define PC_TEST_FAKE_PERIODIC_VIDEO_SOURCE_H_
#include <memory>
#include "api/video/video_source_interface.h"
#include "media/base/fake_frame_source.h"
#include "media/base/video_broadcaster.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/task_queue_for_test.h"
#include "rtc_base/task_utils/repeating_task.h"
namespace webrtc {
class FakePeriodicVideoSource final
: public rtc::VideoSourceInterface<VideoFrame> {
public:
static constexpr int kDefaultFrameIntervalMs = 33;
static constexpr int kDefaultWidth = 640;
static constexpr int kDefaultHeight = 480;
struct Config {
int width = kDefaultWidth;
int height = kDefaultHeight;
int frame_interval_ms = kDefaultFrameIntervalMs;
VideoRotation rotation = kVideoRotation_0;
int64_t timestamp_offset_ms = 0;
};
FakePeriodicVideoSource() : FakePeriodicVideoSource(Config()) {}
explicit FakePeriodicVideoSource(Config config)
: frame_source_(
config.width,
config.height,
config.frame_interval_ms * rtc::kNumMicrosecsPerMillisec,
config.timestamp_offset_ms * rtc::kNumMicrosecsPerMillisec),
task_queue_(std::make_unique<TaskQueueForTest>(
"FakePeriodicVideoTrackSource")) {
frame_source_.SetRotation(config.rotation);
TimeDelta frame_interval = TimeDelta::Millis(config.frame_interval_ms);
repeating_task_handle_ =
RepeatingTaskHandle::Start(task_queue_->Get(), [this, frame_interval] {
if (broadcaster_.wants().rotation_applied) {
broadcaster_.OnFrame(frame_source_.GetFrameRotationApplied());
} else {
broadcaster_.OnFrame(frame_source_.GetFrame());
}
return frame_interval;
});
}
rtc::VideoSinkWants wants() const {
MutexLock lock(&mutex_);
return wants_;
}
void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {
RTC_DCHECK(thread_checker_.IsCurrent());
broadcaster_.RemoveSink(sink);
}
void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
const rtc::VideoSinkWants& wants) override {
RTC_DCHECK(thread_checker_.IsCurrent());
{
MutexLock lock(&mutex_);
wants_ = wants;
}
broadcaster_.AddOrUpdateSink(sink, wants);
}
void Stop() {
RTC_DCHECK(task_queue_);
task_queue_->SendTask([&]() { repeating_task_handle_.Stop(); });
task_queue_.reset();
}
private:
SequenceChecker thread_checker_{SequenceChecker::kDetached};
rtc::VideoBroadcaster broadcaster_;
cricket::FakeFrameSource frame_source_;
mutable Mutex mutex_;
rtc::VideoSinkWants wants_ RTC_GUARDED_BY(&mutex_);
std::unique_ptr<TaskQueueForTest> task_queue_;
RepeatingTaskHandle repeating_task_handle_;
};
} // namespace webrtc
#endif // PC_TEST_FAKE_PERIODIC_VIDEO_SOURCE_H_

View file

@ -0,0 +1,46 @@
/*
* Copyright 2018 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 PC_TEST_FAKE_PERIODIC_VIDEO_TRACK_SOURCE_H_
#define PC_TEST_FAKE_PERIODIC_VIDEO_TRACK_SOURCE_H_
#include "pc/test/fake_periodic_video_source.h"
#include "pc/video_track_source.h"
namespace webrtc {
// A VideoTrackSource generating frames with configured size and frame interval.
class FakePeriodicVideoTrackSource : public VideoTrackSource {
public:
explicit FakePeriodicVideoTrackSource(bool remote)
: FakePeriodicVideoTrackSource(FakePeriodicVideoSource::Config(),
remote) {}
FakePeriodicVideoTrackSource(FakePeriodicVideoSource::Config config,
bool remote)
: VideoTrackSource(remote), source_(config) {}
~FakePeriodicVideoTrackSource() = default;
FakePeriodicVideoSource& fake_periodic_source() { return source_; }
const FakePeriodicVideoSource& fake_periodic_source() const {
return source_;
}
protected:
rtc::VideoSourceInterface<VideoFrame>* source() override { return &source_; }
private:
FakePeriodicVideoSource source_;
};
} // namespace webrtc
#endif // PC_TEST_FAKE_PERIODIC_VIDEO_TRACK_SOURCE_H_

View file

@ -0,0 +1,222 @@
/*
* Copyright 2013 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 PC_TEST_FAKE_RTC_CERTIFICATE_GENERATOR_H_
#define PC_TEST_FAKE_RTC_CERTIFICATE_GENERATOR_H_
#include <string>
#include <utility>
#include "absl/types/optional.h"
#include "api/peer_connection_interface.h"
#include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
#include "rtc_base/rtc_certificate.h"
#include "rtc_base/rtc_certificate_generator.h"
// RSA with mod size 1024, pub exp 0x10001.
static const rtc::RTCCertificatePEM kRsaPems[] = {
rtc::RTCCertificatePEM(
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n"
"czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n"
"rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n"
"5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n"
"mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n"
"2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n"
"CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n"
"WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n"
"kdqANep0uwZciiNiWxsQrCHztywOvbFhdp8iYVFG9EK8DMY41Y5TxUwsHD+67zao\n"
"ZNqJAkEA1suLUP/GvL8IwuRneQd2tWDqqRQ/Td3qq03hP7e77XtF/buya3Ghclo5\n"
"54czUR89QyVfJEC6278nzA7n2h1uVQJAcG6mztNL6ja/dKZjYZye2CY44QjSlLo0\n"
"MTgTSjdfg/28fFn2Jjtqf9Pi/X+50LWI/RcYMC2no606wRk9kyOuIQJBAK6VSAim\n"
"1pOEjsYQn0X5KEIrz1G3bfCbB848Ime3U2/FWlCHMr6ch8kCZ5d1WUeJD3LbwMNG\n"
"UCXiYxSsu20QNVw=\n"
"-----END RSA PRIVATE KEY-----\n",
"-----BEGIN CERTIFICATE-----\n"
"MIIBmTCCAQKgAwIBAgIEbzBSAjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZX\n"
"ZWJSVEMwHhcNMTQwMTAyMTgyNDQ3WhcNMTQwMjAxMTgyNDQ3WjARMQ8wDQYDVQQD\n"
"EwZXZWJSVEMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYRkbhmI7kVA/rM\n"
"czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n"
"rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n"
"5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAUflI\n"
"VUe5Krqf5RVa5C3u/UTAOAUJBiDS3VANTCLBxjuMsvqOG0WvaYWP3HYPgrz0jXK2\n"
"LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n"
"UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n"
"-----END CERTIFICATE-----\n"),
rtc::RTCCertificatePEM(
"-----BEGIN RSA PRIVATE KEY-----\n"
"MIICXQIBAAKBgQDeYqlyJ1wuiMsi905e3X81/WA/G3ym50PIDZBVtSwZi7JVQPgj\n"
"Bl8CPZMvDh9EwB4Ji9ytA8dZZbQ4WbJWPr73zPpJSCvQqz6sOXSlenBRi72acNaQ\n"
"sOR/qPvviJx5I6Hqo4qemfnjZhAW85a5BpgrAwKgMLIQTHCTLWwVSyrDrwIDAQAB\n"
"AoGARni9eY8/hv+SX+I+05EdXt6MQXNUbQ+cSykBNCfVccLzIFEWUQMT2IHqwl6X\n"
"ShIXcq7/n1QzOAEiuzixauM3YHg4xZ1Um2Ha9a7ig5Xg4v6b43bmMkNE6LkoAtYs\n"
"qnQdfMh442b1liDud6IMb1Qk0amt3fSrgRMc547TZQVx4QECQQDxUeDm94r3p4ng\n"
"5rCLLC1K5/6HSTZsh7jatKPlz7GfP/IZlYV7iE5784/n0wRiCjZOS7hQRy/8m2Gp\n"
"pf4aZq+DAkEA6+np4d36FYikydvUrupLT3FkdRHGn/v83qOll/VmeNh+L1xMZlIP\n"
"tM26hAXCcQb7O5+J9y3cx2CAQsBS11ZXZQJAfGgTo76WG9p5UEJdXUInD2jOZPwv\n"
"XIATolxh6kXKcijLLLlSmT7KB0inNYIpzkkpee+7U1d/u6B3FriGaSHq9QJBAM/J\n"
"ICnDdLCgwNvWVraVQC3BpwSB2pswvCFwq7py94V60XFvbw80Ogc6qIv98qvQxVlX\n"
"hJIEgA/PjEi+0ng94Q0CQQDm8XSDby35gmjO+6eRmJtAjtB7nguLvrPXM6CPXRmD\n"
"sRoBocpHw6j9UdzZ6qYG0FkdXZghezXFY58ro2BYYRR3\n"
"-----END RSA PRIVATE KEY-----\n",
"-----BEGIN CERTIFICATE-----\n"
"MIICWDCCAcGgAwIBAgIJALgDjxMbBOhbMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\n"
"BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n"
"aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTEzMjIzMjEzWhcNMTYxMTEyMjIzMjEzWjBF\n"
"MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n"
"ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
"gQDeYqlyJ1wuiMsi905e3X81/WA/G3ym50PIDZBVtSwZi7JVQPgjBl8CPZMvDh9E\n"
"wB4Ji9ytA8dZZbQ4WbJWPr73zPpJSCvQqz6sOXSlenBRi72acNaQsOR/qPvviJx5\n"
"I6Hqo4qemfnjZhAW85a5BpgrAwKgMLIQTHCTLWwVSyrDrwIDAQABo1AwTjAdBgNV\n"
"HQ4EFgQUx2tbJdlcSTCepn09UdYORXKuSTAwHwYDVR0jBBgwFoAUx2tbJdlcSTCe\n"
"pn09UdYORXKuSTAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAmp9Id\n"
"E716gHMqeBG4S2FCgVFCr0a0ugkaneQAN/c2L9CbMemEN9W6jvucUIVOtYd90dDW\n"
"lXuowWmT/JctPe3D2qt4yvYW3puECHk2tVQmrJOZiZiTRtWm6HxkmoUYHYp/DtaS\n"
"1Xe29gSTnZtI5sQCrGMzk3SGRSSs7ejLKiVDBQ==\n"
"-----END CERTIFICATE-----\n")};
// ECDSA with EC_NIST_P256.
// These PEM strings were created by generating an identity with
// `SSLIdentity::Create` and invoking `identity->PrivateKeyToPEMString()`,
// `identity->PublicKeyToPEMString()` and
// `identity->certificate().ToPEMString()`.
static const rtc::RTCCertificatePEM kEcdsaPems[] = {
rtc::RTCCertificatePEM(
"-----BEGIN PRIVATE KEY-----\n"
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg+qaRsR5uHtqG689M\n"
"A3PHSJNeVpyi5wUKCft62h0UWy+hRANCAAS5Mjc85q9fVq4ln+zOPlaEC/Rzj5Pb\n"
"MVZtf1x/8k2KsbmyZoAMDX2yer/atEuXmItMe3yd6/DXnvboU//D3Lyt\n"
"-----END PRIVATE KEY-----\n",
"-----BEGIN CERTIFICATE-----\n"
"MIIBFTCBu6ADAgECAgkA30tGY5XG7oowCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF\n"
"dGVzdDMwHhcNMTYwNTA5MDkxODA4WhcNMTYwNjA5MDkxODA4WjAQMQ4wDAYDVQQD\n"
"DAV0ZXN0MzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLkyNzzmr19WriWf7M4+\n"
"VoQL9HOPk9sxVm1/XH/yTYqxubJmgAwNfbJ6v9q0S5eYi0x7fJ3r8Nee9uhT/8Pc\n"
"vK0wCgYIKoZIzj0EAwIDSQAwRgIhAIIc3+CqfkZ9lLwTj1PvUtt3KhnqF2kD0War\n"
"cCoTBbCxAiEAyp9Cn4vo2ZBhRIVDKyoxmwak8Z0PAVhJAQaWCgoY2D4=\n"
"-----END CERTIFICATE-----\n"),
rtc::RTCCertificatePEM(
"-----BEGIN PRIVATE KEY-----\n"
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghL/G4JRYnuDNbQuh\n"
"LqkytcE39Alsq6FItDVFgOesfCmhRANCAATd53FjPLyVUcwYguEPbSJM03fP6Rx5\n"
"GY1dEZ00+ZykjJI83VfDAyvmpRuGahNtBH0hc+7xkDCbeo6TM0tN35xr\n"
"-----END PRIVATE KEY-----\n",
"-----BEGIN CERTIFICATE-----\n"
"MIIBFDCBu6ADAgECAgkArZYdXMyJ5rswCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF\n"
"dGVzdDQwHhcNMTYwNTA5MDkxODA4WhcNMTYwNjA5MDkxODA4WjAQMQ4wDAYDVQQD\n"
"DAV0ZXN0NDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABN3ncWM8vJVRzBiC4Q9t\n"
"IkzTd8/pHHkZjV0RnTT5nKSMkjzdV8MDK+alG4ZqE20EfSFz7vGQMJt6jpMzS03f\n"
"nGswCgYIKoZIzj0EAwIDSAAwRQIgb/LBc8OtsC5lEDyjCP6M9xt5mwzUNrQBOFWZ\n"
"1fE/g68CIQD7uoFfbiq6dTp8ZwzbwQ8jJf08KjriamqA9OW/4268Dw==\n"
"-----END CERTIFICATE-----\n")};
class FakeRTCCertificateGenerator
: public rtc::RTCCertificateGeneratorInterface {
public:
FakeRTCCertificateGenerator() : should_fail_(false), should_wait_(false) {}
void set_should_fail(bool should_fail) { should_fail_ = should_fail; }
// If set to true, stalls the generation of the fake certificate until it is
// set to false.
void set_should_wait(bool should_wait) { should_wait_ = should_wait; }
void use_original_key() { key_index_ = 0; }
void use_alternate_key() { key_index_ = 1; }
int generated_certificates() { return generated_certificates_; }
int generated_failures() { return generated_failures_; }
void GenerateCertificateAsync(const rtc::KeyParams& key_params,
const absl::optional<uint64_t>& expires_ms,
Callback callback) override {
// The certificates are created from constant PEM strings and use its coded
// expiration time, we do not support modifying it.
RTC_DCHECK(!expires_ms);
// Only supports RSA-1024-0x10001 and ECDSA-P256.
if (key_params.type() == rtc::KT_RSA) {
RTC_DCHECK_EQ(key_params.rsa_params().mod_size, 1024);
RTC_DCHECK_EQ(key_params.rsa_params().pub_exp, 0x10001);
} else {
RTC_DCHECK_EQ(key_params.type(), rtc::KT_ECDSA);
RTC_DCHECK_EQ(key_params.ec_curve(), rtc::EC_NIST_P256);
}
rtc::KeyType key_type = key_params.type();
webrtc::TaskQueueBase::Current()->PostTask(
[this, key_type, callback = std::move(callback)]() mutable {
GenerateCertificate(key_type, std::move(callback));
});
}
static rtc::scoped_refptr<rtc::RTCCertificate> GenerateCertificate() {
switch (rtc::KT_DEFAULT) {
case rtc::KT_RSA:
return rtc::RTCCertificate::FromPEM(kRsaPems[0]);
case rtc::KT_ECDSA:
return rtc::RTCCertificate::FromPEM(kEcdsaPems[0]);
default:
RTC_DCHECK_NOTREACHED();
return nullptr;
}
}
private:
const rtc::RTCCertificatePEM& get_pem(const rtc::KeyType& key_type) const {
switch (key_type) {
case rtc::KT_RSA:
return kRsaPems[key_index_];
case rtc::KT_ECDSA:
return kEcdsaPems[key_index_];
default:
RTC_DCHECK_NOTREACHED();
return kEcdsaPems[key_index_];
}
}
const std::string& get_key(const rtc::KeyType& key_type) const {
return get_pem(key_type).private_key();
}
const std::string& get_cert(const rtc::KeyType& key_type) const {
return get_pem(key_type).certificate();
}
void GenerateCertificate(rtc::KeyType key_type, Callback callback) {
// If the certificate generation should be stalled, re-post this same
// message to the queue with a small delay so as to wait in a loop until
// set_should_wait(false) is called.
if (should_wait_) {
webrtc::TaskQueueBase::Current()->PostDelayedTask(
[this, key_type, callback = std::move(callback)]() mutable {
GenerateCertificate(key_type, std::move(callback));
},
webrtc::TimeDelta::Millis(1));
return;
}
if (should_fail_) {
++generated_failures_;
std::move(callback)(nullptr);
} else {
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc::RTCCertificate::FromPEM(get_pem(key_type));
RTC_DCHECK(certificate);
++generated_certificates_;
std::move(callback)(std::move(certificate));
}
}
bool should_fail_;
bool should_wait_;
int key_index_ = 0;
int generated_certificates_ = 0;
int generated_failures_ = 0;
};
#endif // PC_TEST_FAKE_RTC_CERTIFICATE_GENERATOR_H_

View file

@ -0,0 +1,33 @@
/*
* Copyright 2012 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 PC_TEST_FAKE_VIDEO_TRACK_RENDERER_H_
#define PC_TEST_FAKE_VIDEO_TRACK_RENDERER_H_
#include "api/media_stream_interface.h"
#include "media/base/fake_video_renderer.h"
namespace webrtc {
class FakeVideoTrackRenderer : public cricket::FakeVideoRenderer {
public:
explicit FakeVideoTrackRenderer(VideoTrackInterface* video_track)
: video_track_(video_track) {
video_track_->AddOrUpdateSink(this, rtc::VideoSinkWants());
}
~FakeVideoTrackRenderer() { video_track_->RemoveSink(this); }
private:
rtc::scoped_refptr<VideoTrackInterface> video_track_;
};
} // namespace webrtc
#endif // PC_TEST_FAKE_VIDEO_TRACK_RENDERER_H_

View file

@ -0,0 +1,54 @@
/*
* Copyright 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 PC_TEST_FAKE_VIDEO_TRACK_SOURCE_H_
#define PC_TEST_FAKE_VIDEO_TRACK_SOURCE_H_
#include "api/media_stream_interface.h"
#include "media/base/video_broadcaster.h"
#include "pc/video_track_source.h"
namespace webrtc {
// A minimal implementation of VideoTrackSource. Includes a VideoBroadcaster for
// injection of frames.
class FakeVideoTrackSource : public VideoTrackSource {
public:
static rtc::scoped_refptr<FakeVideoTrackSource> Create(bool is_screencast) {
return rtc::make_ref_counted<FakeVideoTrackSource>(is_screencast);
}
static rtc::scoped_refptr<FakeVideoTrackSource> Create() {
return Create(false);
}
bool is_screencast() const override { return is_screencast_; }
void InjectFrame(const VideoFrame& frame) {
video_broadcaster_.OnFrame(frame);
}
protected:
explicit FakeVideoTrackSource(bool is_screencast)
: VideoTrackSource(false /* remote */), is_screencast_(is_screencast) {}
~FakeVideoTrackSource() override = default;
rtc::VideoSourceInterface<VideoFrame>* source() override {
return &video_broadcaster_;
}
private:
const bool is_screencast_;
rtc::VideoBroadcaster video_broadcaster_;
};
} // namespace webrtc
#endif // PC_TEST_FAKE_VIDEO_TRACK_SOURCE_H_

View file

@ -0,0 +1,92 @@
/*
* Copyright 2018 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 PC_TEST_FRAME_GENERATOR_CAPTURER_VIDEO_TRACK_SOURCE_H_
#define PC_TEST_FRAME_GENERATOR_CAPTURER_VIDEO_TRACK_SOURCE_H_
#include <memory>
#include <utility>
#include "api/task_queue/default_task_queue_factory.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/test/create_frame_generator.h"
#include "pc/video_track_source.h"
#include "test/frame_generator_capturer.h"
namespace webrtc {
// Implements a VideoTrackSourceInterface to be used for creating VideoTracks.
// The video source is generated using a FrameGeneratorCapturer, specifically
// a SquareGenerator that generates frames with randomly sized and colored
// squares.
class FrameGeneratorCapturerVideoTrackSource : public VideoTrackSource {
public:
static const int kDefaultFramesPerSecond = 30;
static const int kDefaultWidth = 640;
static const int kDefaultHeight = 480;
static const int kNumSquaresGenerated = 50;
struct Config {
int frames_per_second = kDefaultFramesPerSecond;
int width = kDefaultWidth;
int height = kDefaultHeight;
int num_squares_generated = 50;
};
FrameGeneratorCapturerVideoTrackSource(Config config,
Clock* clock,
bool is_screencast)
: VideoTrackSource(false /* remote */),
task_queue_factory_(CreateDefaultTaskQueueFactory()),
is_screencast_(is_screencast) {
video_capturer_ = std::make_unique<test::FrameGeneratorCapturer>(
clock,
test::CreateSquareFrameGenerator(config.width, config.height,
absl::nullopt,
config.num_squares_generated),
config.frames_per_second, *task_queue_factory_);
video_capturer_->Init();
}
FrameGeneratorCapturerVideoTrackSource(
std::unique_ptr<test::FrameGeneratorCapturer> video_capturer,
bool is_screencast)
: VideoTrackSource(false /* remote */),
video_capturer_(std::move(video_capturer)),
is_screencast_(is_screencast) {}
~FrameGeneratorCapturerVideoTrackSource() = default;
void Start() {
SetState(kLive);
video_capturer_->Start();
}
void Stop() {
SetState(kMuted);
video_capturer_->Stop();
}
bool is_screencast() const override { return is_screencast_; }
protected:
rtc::VideoSourceInterface<VideoFrame>* source() override {
return video_capturer_.get();
}
private:
const std::unique_ptr<TaskQueueFactory> task_queue_factory_;
std::unique_ptr<test::FrameGeneratorCapturer> video_capturer_;
const bool is_screencast_;
};
} // namespace webrtc
#endif // PC_TEST_FRAME_GENERATOR_CAPTURER_VIDEO_TRACK_SOURCE_H_

View file

@ -0,0 +1,96 @@
/*
* Copyright 2012 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 "pc/test/integration_test_helpers.h"
namespace webrtc {
PeerConnectionInterface::RTCOfferAnswerOptions IceRestartOfferAnswerOptions() {
PeerConnectionInterface::RTCOfferAnswerOptions options;
options.ice_restart = true;
return options;
}
void RemoveSsrcsAndMsids(cricket::SessionDescription* desc) {
for (ContentInfo& content : desc->contents()) {
content.media_description()->mutable_streams().clear();
}
desc->set_msid_signaling(0);
}
void RemoveSsrcsAndKeepMsids(cricket::SessionDescription* desc) {
for (ContentInfo& content : desc->contents()) {
std::string track_id;
std::vector<std::string> stream_ids;
if (!content.media_description()->streams().empty()) {
const StreamParams& first_stream =
content.media_description()->streams()[0];
track_id = first_stream.id;
stream_ids = first_stream.stream_ids();
}
content.media_description()->mutable_streams().clear();
StreamParams new_stream;
new_stream.id = track_id;
new_stream.set_stream_ids(stream_ids);
content.media_description()->AddStream(new_stream);
}
}
int FindFirstMediaStatsIndexByKind(
const std::string& kind,
const std::vector<const RTCInboundRtpStreamStats*>& inbound_rtps) {
for (size_t i = 0; i < inbound_rtps.size(); i++) {
if (*inbound_rtps[i]->kind == kind) {
return i;
}
}
return -1;
}
void ReplaceFirstSsrc(StreamParams& stream, uint32_t ssrc) {
stream.ssrcs[0] = ssrc;
for (auto& group : stream.ssrc_groups) {
group.ssrcs[0] = ssrc;
}
}
TaskQueueMetronome::TaskQueueMetronome(TimeDelta tick_period)
: tick_period_(tick_period) {}
TaskQueueMetronome::~TaskQueueMetronome() {
RTC_DCHECK_RUN_ON(&sequence_checker_);
}
void TaskQueueMetronome::RequestCallOnNextTick(
absl::AnyInvocable<void() &&> callback) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
callbacks_.push_back(std::move(callback));
// Only schedule a tick callback for the first `callback` addition.
// Schedule on the current task queue to comply with RequestCallOnNextTick
// requirements.
if (callbacks_.size() == 1) {
TaskQueueBase::Current()->PostDelayedTask(
SafeTask(safety_.flag(),
[this] {
RTC_DCHECK_RUN_ON(&sequence_checker_);
std::vector<absl::AnyInvocable<void() &&>> callbacks;
callbacks_.swap(callbacks);
for (auto& callback : callbacks)
std::move(callback)();
}),
tick_period_);
}
}
TimeDelta TaskQueueMetronome::TickPeriod() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
return tick_period_;
}
} // namespace webrtc

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,88 @@
/*
* Copyright 2018 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 PC_TEST_MOCK_CHANNEL_INTERFACE_H_
#define PC_TEST_MOCK_CHANNEL_INTERFACE_H_
#include <string>
#include <vector>
#include "media/base/media_channel.h"
#include "pc/channel_interface.h"
#include "test/gmock.h"
namespace cricket {
// Mock class for BaseChannel.
// Use this class in unit tests to avoid dependecy on a specific
// implementation of BaseChannel.
class MockChannelInterface : public cricket::ChannelInterface {
public:
MOCK_METHOD(cricket::MediaType, media_type, (), (const, override));
MOCK_METHOD(VideoChannel*, AsVideoChannel, (), (override));
MOCK_METHOD(VoiceChannel*, AsVoiceChannel, (), (override));
MOCK_METHOD(MediaSendChannelInterface*, media_send_channel, (), (override));
MOCK_METHOD(VoiceMediaSendChannelInterface*,
voice_media_send_channel,
(),
(override));
MOCK_METHOD(VideoMediaSendChannelInterface*,
video_media_send_channel,
(),
(override));
MOCK_METHOD(MediaReceiveChannelInterface*,
media_receive_channel,
(),
(override));
MOCK_METHOD(VoiceMediaReceiveChannelInterface*,
voice_media_receive_channel,
(),
(override));
MOCK_METHOD(VideoMediaReceiveChannelInterface*,
video_media_receive_channel,
(),
(override));
MOCK_METHOD(absl::string_view, transport_name, (), (const, override));
MOCK_METHOD(const std::string&, mid, (), (const, override));
MOCK_METHOD(void, Enable, (bool), (override));
MOCK_METHOD(void,
SetFirstPacketReceivedCallback,
(std::function<void()>),
(override));
MOCK_METHOD(bool,
SetLocalContent,
(const cricket::MediaContentDescription*,
webrtc::SdpType,
std::string&),
(override));
MOCK_METHOD(bool,
SetRemoteContent,
(const cricket::MediaContentDescription*,
webrtc::SdpType,
std::string&),
(override));
MOCK_METHOD(bool, SetPayloadTypeDemuxingEnabled, (bool), (override));
MOCK_METHOD(const std::vector<StreamParams>&,
local_streams,
(),
(const, override));
MOCK_METHOD(const std::vector<StreamParams>&,
remote_streams,
(),
(const, override));
MOCK_METHOD(bool,
SetRtpTransport,
(webrtc::RtpTransportInternal*),
(override));
};
} // namespace cricket
#endif // PC_TEST_MOCK_CHANNEL_INTERFACE_H_

View file

@ -0,0 +1,79 @@
/*
* Copyright 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 PC_TEST_MOCK_DATA_CHANNEL_H_
#define PC_TEST_MOCK_DATA_CHANNEL_H_
#include <string>
#include <utility>
#include "pc/sctp_data_channel.h"
#include "test/gmock.h"
namespace webrtc {
class MockSctpDataChannel : public SctpDataChannel {
public:
MockSctpDataChannel(
rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
int id,
DataState state)
: MockSctpDataChannel(std::move(controller),
id,
"MockSctpDataChannel",
state,
"someProtocol",
0,
0,
0,
0) {}
MockSctpDataChannel(
rtc::WeakPtr<SctpDataChannelControllerInterface> controller,
int id,
const std::string& label,
DataState state,
const std::string& protocol,
uint32_t messages_sent,
uint64_t bytes_sent,
uint32_t messages_received,
uint64_t bytes_received,
const InternalDataChannelInit& config = InternalDataChannelInit(),
rtc::Thread* signaling_thread = rtc::Thread::Current(),
rtc::Thread* network_thread = rtc::Thread::Current())
: SctpDataChannel(config,
std::move(controller),
label,
false,
signaling_thread,
network_thread) {
EXPECT_CALL(*this, id()).WillRepeatedly(::testing::Return(id));
EXPECT_CALL(*this, state()).WillRepeatedly(::testing::Return(state));
EXPECT_CALL(*this, protocol()).WillRepeatedly(::testing::Return(protocol));
EXPECT_CALL(*this, messages_sent())
.WillRepeatedly(::testing::Return(messages_sent));
EXPECT_CALL(*this, bytes_sent())
.WillRepeatedly(::testing::Return(bytes_sent));
EXPECT_CALL(*this, messages_received())
.WillRepeatedly(::testing::Return(messages_received));
EXPECT_CALL(*this, bytes_received())
.WillRepeatedly(::testing::Return(bytes_received));
}
MOCK_METHOD(int, id, (), (const, override));
MOCK_METHOD(DataState, state, (), (const, override));
MOCK_METHOD(std::string, protocol, (), (const, override));
MOCK_METHOD(uint32_t, messages_sent, (), (const, override));
MOCK_METHOD(uint64_t, bytes_sent, (), (const, override));
MOCK_METHOD(uint32_t, messages_received, (), (const, override));
MOCK_METHOD(uint64_t, bytes_received, (), (const, override));
};
} // namespace webrtc
#endif // PC_TEST_MOCK_DATA_CHANNEL_H_

View file

@ -0,0 +1,329 @@
/*
* Copyright 2022 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 PC_TEST_MOCK_PEER_CONNECTION_INTERNAL_H_
#define PC_TEST_MOCK_PEER_CONNECTION_INTERNAL_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "modules/audio_device/include/audio_device.h"
#include "pc/peer_connection_internal.h"
#include "test/gmock.h"
namespace webrtc {
class MockPeerConnectionInternal : public PeerConnectionInternal {
public:
MockPeerConnectionInternal() {}
~MockPeerConnectionInternal() = default;
// PeerConnectionInterface
MOCK_METHOD(rtc::scoped_refptr<StreamCollectionInterface>,
local_streams,
(),
(override));
MOCK_METHOD(rtc::scoped_refptr<StreamCollectionInterface>,
remote_streams,
(),
(override));
MOCK_METHOD(bool, AddStream, (MediaStreamInterface*), (override));
MOCK_METHOD(void, RemoveStream, (MediaStreamInterface*), (override));
MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>,
AddTrack,
(rtc::scoped_refptr<MediaStreamTrackInterface>,
const std::vector<std::string>&),
(override));
MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>,
AddTrack,
(rtc::scoped_refptr<MediaStreamTrackInterface>,
const std::vector<std::string>&,
const std::vector<RtpEncodingParameters>&),
(override));
MOCK_METHOD(RTCError,
RemoveTrackOrError,
(rtc::scoped_refptr<RtpSenderInterface>),
(override));
MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
AddTransceiver,
(rtc::scoped_refptr<MediaStreamTrackInterface>),
(override));
MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
AddTransceiver,
(rtc::scoped_refptr<MediaStreamTrackInterface>,
const RtpTransceiverInit&),
(override));
MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
AddTransceiver,
(cricket::MediaType),
(override));
MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
AddTransceiver,
(cricket::MediaType, const RtpTransceiverInit&),
(override));
MOCK_METHOD(rtc::scoped_refptr<RtpSenderInterface>,
CreateSender,
(const std::string&, const std::string&),
(override));
MOCK_METHOD(std::vector<rtc::scoped_refptr<RtpSenderInterface>>,
GetSenders,
(),
(const, override));
MOCK_METHOD(std::vector<rtc::scoped_refptr<RtpReceiverInterface>>,
GetReceivers,
(),
(const, override));
MOCK_METHOD(std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>,
GetTransceivers,
(),
(const, override));
MOCK_METHOD(bool,
GetStats,
(StatsObserver*, MediaStreamTrackInterface*, StatsOutputLevel),
(override));
MOCK_METHOD(void, GetStats, (RTCStatsCollectorCallback*), (override));
MOCK_METHOD(void,
GetStats,
(rtc::scoped_refptr<RtpSenderInterface>,
rtc::scoped_refptr<RTCStatsCollectorCallback>),
(override));
MOCK_METHOD(void,
GetStats,
(rtc::scoped_refptr<RtpReceiverInterface>,
rtc::scoped_refptr<RTCStatsCollectorCallback>),
(override));
MOCK_METHOD(void, ClearStatsCache, (), (override));
MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<DataChannelInterface>>,
CreateDataChannelOrError,
(const std::string&, const DataChannelInit*),
(override));
MOCK_METHOD(SessionDescriptionInterface*,
local_description,
(),
(const, override));
MOCK_METHOD(SessionDescriptionInterface*,
remote_description,
(),
(const, override));
MOCK_METHOD(SessionDescriptionInterface*,
current_local_description,
(),
(const, override));
MOCK_METHOD(SessionDescriptionInterface*,
current_remote_description,
(),
(const, override));
MOCK_METHOD(SessionDescriptionInterface*,
pending_local_description,
(),
(const, override));
MOCK_METHOD(SessionDescriptionInterface*,
pending_remote_description,
(),
(const, override));
MOCK_METHOD(void, RestartIce, (), (override));
MOCK_METHOD(void,
CreateOffer,
(CreateSessionDescriptionObserver*, const RTCOfferAnswerOptions&),
(override));
MOCK_METHOD(void,
CreateAnswer,
(CreateSessionDescriptionObserver*, const RTCOfferAnswerOptions&),
(override));
MOCK_METHOD(void,
SetLocalDescription,
(SetSessionDescriptionObserver*, SessionDescriptionInterface*),
(override));
MOCK_METHOD(void,
SetRemoteDescription,
(SetSessionDescriptionObserver*, SessionDescriptionInterface*),
(override));
MOCK_METHOD(void,
SetRemoteDescription,
(std::unique_ptr<SessionDescriptionInterface>,
rtc::scoped_refptr<SetRemoteDescriptionObserverInterface>),
(override));
MOCK_METHOD(PeerConnectionInterface::RTCConfiguration,
GetConfiguration,
(),
(override));
MOCK_METHOD(RTCError,
SetConfiguration,
(const PeerConnectionInterface::RTCConfiguration&),
(override));
MOCK_METHOD(bool,
AddIceCandidate,
(const IceCandidateInterface*),
(override));
MOCK_METHOD(bool,
RemoveIceCandidates,
(const std::vector<cricket::Candidate>&),
(override));
MOCK_METHOD(RTCError, SetBitrate, (const BitrateSettings&), (override));
MOCK_METHOD(void,
ReconfigureBandwidthEstimation,
(const BandwidthEstimationSettings&),
(override));
MOCK_METHOD(void, SetAudioPlayout, (bool), (override));
MOCK_METHOD(void, SetAudioRecording, (bool), (override));
MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>,
LookupDtlsTransportByMid,
(const std::string&),
(override));
MOCK_METHOD(rtc::scoped_refptr<SctpTransportInterface>,
GetSctpTransport,
(),
(const, override));
MOCK_METHOD(SignalingState, signaling_state, (), (override));
MOCK_METHOD(IceConnectionState, ice_connection_state, (), (override));
MOCK_METHOD(IceConnectionState,
standardized_ice_connection_state,
(),
(override));
MOCK_METHOD(PeerConnectionState, peer_connection_state, (), (override));
MOCK_METHOD(IceGatheringState, ice_gathering_state, (), (override));
MOCK_METHOD(absl::optional<bool>, can_trickle_ice_candidates, (), (override));
MOCK_METHOD(bool,
StartRtcEventLog,
(std::unique_ptr<RtcEventLogOutput>, int64_t),
(override));
MOCK_METHOD(bool,
StartRtcEventLog,
(std::unique_ptr<RtcEventLogOutput>),
(override));
MOCK_METHOD(void, StopRtcEventLog, (), (override));
MOCK_METHOD(void, Close, (), (override));
MOCK_METHOD(rtc::Thread*, signaling_thread, (), (const, override));
// PeerConnectionSdpMethods
MOCK_METHOD(std::string, session_id, (), (const, override));
MOCK_METHOD(bool, NeedsIceRestart, (const std::string&), (const, override));
MOCK_METHOD(absl::optional<std::string>, sctp_mid, (), (const, override));
MOCK_METHOD(PeerConnectionInterface::RTCConfiguration*,
configuration,
(),
(const, override));
MOCK_METHOD(void,
ReportSdpBundleUsage,
(const SessionDescriptionInterface&),
(override));
MOCK_METHOD(PeerConnectionMessageHandler*, message_handler, (), (override));
MOCK_METHOD(RtpTransmissionManager*, rtp_manager, (), (override));
MOCK_METHOD(const RtpTransmissionManager*,
rtp_manager,
(),
(const, override));
MOCK_METHOD(bool, dtls_enabled, (), (const, override));
MOCK_METHOD(const PeerConnectionFactoryInterface::Options*,
options,
(),
(const, override));
MOCK_METHOD(CryptoOptions, GetCryptoOptions, (), (override));
MOCK_METHOD(JsepTransportController*, transport_controller_s, (), (override));
MOCK_METHOD(JsepTransportController*, transport_controller_n, (), (override));
MOCK_METHOD(DataChannelController*, data_channel_controller, (), (override));
MOCK_METHOD(cricket::PortAllocator*, port_allocator, (), (override));
MOCK_METHOD(LegacyStatsCollector*, legacy_stats, (), (override));
MOCK_METHOD(PeerConnectionObserver*, Observer, (), (const, override));
MOCK_METHOD(absl::optional<rtc::SSLRole>, GetSctpSslRole_n, (), (override));
MOCK_METHOD(PeerConnectionInterface::IceConnectionState,
ice_connection_state_internal,
(),
(override));
MOCK_METHOD(void,
SetIceConnectionState,
(PeerConnectionInterface::IceConnectionState),
(override));
MOCK_METHOD(void, NoteUsageEvent, (UsageEvent), (override));
MOCK_METHOD(bool, IsClosed, (), (const, override));
MOCK_METHOD(bool, IsUnifiedPlan, (), (const, override));
MOCK_METHOD(bool,
ValidateBundleSettings,
(const cricket::SessionDescription*,
(const std::map<std::string, const cricket::ContentGroup*>&)),
(override));
MOCK_METHOD(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
AddTransceiver,
(cricket::MediaType,
rtc::scoped_refptr<MediaStreamTrackInterface>,
const RtpTransceiverInit&,
bool),
(override));
MOCK_METHOD(void, StartSctpTransport, (int, int, int), (override));
MOCK_METHOD(void,
AddRemoteCandidate,
(const std::string&, const cricket::Candidate&),
(override));
MOCK_METHOD(Call*, call_ptr, (), (override));
MOCK_METHOD(bool, SrtpRequired, (), (const, override));
MOCK_METHOD(bool,
CreateDataChannelTransport,
(absl::string_view),
(override));
MOCK_METHOD(void, DestroyDataChannelTransport, (RTCError error), (override));
MOCK_METHOD(const FieldTrialsView&, trials, (), (const, override));
// PeerConnectionInternal
MOCK_METHOD(rtc::Thread*, network_thread, (), (const, override));
MOCK_METHOD(rtc::Thread*, worker_thread, (), (const, override));
MOCK_METHOD(bool, initial_offerer, (), (const, override));
MOCK_METHOD(
std::vector<
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>,
GetTransceiversInternal,
(),
(const, override));
MOCK_METHOD(std::vector<DataChannelStats>,
GetDataChannelStats,
(),
(const, override));
MOCK_METHOD(absl::optional<std::string>,
sctp_transport_name,
(),
(const, override));
MOCK_METHOD(cricket::CandidateStatsList,
GetPooledCandidateStats,
(),
(const, override));
MOCK_METHOD((std::map<std::string, cricket::TransportStats>),
GetTransportStatsByNames,
(const std::set<std::string>&),
(override));
MOCK_METHOD(Call::Stats, GetCallStats, (), (override));
MOCK_METHOD(absl::optional<AudioDeviceModule::Stats>,
GetAudioDeviceStats,
(),
(override));
MOCK_METHOD(bool,
GetLocalCertificate,
(const std::string&, rtc::scoped_refptr<rtc::RTCCertificate>*),
(override));
MOCK_METHOD(std::unique_ptr<rtc::SSLCertChain>,
GetRemoteSSLCertChain,
(const std::string&),
(override));
MOCK_METHOD(bool, IceRestartPending, (const std::string&), (const, override));
MOCK_METHOD(bool,
GetSslRole,
(const std::string&, rtc::SSLRole*),
(override));
MOCK_METHOD(void, NoteDataAddedEvent, (), (override));
MOCK_METHOD(void,
OnSctpDataChannelStateChanged,
(int channel_id, DataChannelInterface::DataState),
(override));
};
} // namespace webrtc
#endif // PC_TEST_MOCK_PEER_CONNECTION_INTERNAL_H_

View file

@ -0,0 +1,598 @@
/*
* Copyright 2012 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.
*/
// This file contains mock implementations of observers used in PeerConnection.
// TODO(steveanton): These aren't really mocks and should be renamed.
#ifndef PC_TEST_MOCK_PEER_CONNECTION_OBSERVERS_H_
#define PC_TEST_MOCK_PEER_CONNECTION_OBSERVERS_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "api/data_channel_interface.h"
#include "api/jsep_ice_candidate.h"
#include "pc/stream_collection.h"
#include "rtc_base/checks.h"
namespace webrtc {
class MockPeerConnectionObserver : public PeerConnectionObserver {
public:
struct AddTrackEvent {
explicit AddTrackEvent(
rtc::scoped_refptr<RtpReceiverInterface> event_receiver,
std::vector<rtc::scoped_refptr<MediaStreamInterface>> event_streams)
: receiver(std::move(event_receiver)),
streams(std::move(event_streams)) {
for (auto stream : streams) {
std::vector<rtc::scoped_refptr<MediaStreamTrackInterface>> tracks;
for (auto audio_track : stream->GetAudioTracks()) {
tracks.push_back(audio_track);
}
for (auto video_track : stream->GetVideoTracks()) {
tracks.push_back(video_track);
}
snapshotted_stream_tracks[stream] = tracks;
}
}
rtc::scoped_refptr<RtpReceiverInterface> receiver;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
// This map records the tracks present in each stream at the time the
// OnAddTrack callback was issued.
std::map<rtc::scoped_refptr<MediaStreamInterface>,
std::vector<rtc::scoped_refptr<MediaStreamTrackInterface>>>
snapshotted_stream_tracks;
};
MockPeerConnectionObserver() : remote_streams_(StreamCollection::Create()) {}
virtual ~MockPeerConnectionObserver() {}
void SetPeerConnectionInterface(PeerConnectionInterface* pc) {
pc_ = pc;
if (pc) {
state_ = pc_->signaling_state();
}
}
void OnSignalingChange(
PeerConnectionInterface::SignalingState new_state) override {
RTC_DCHECK(pc_);
RTC_DCHECK(pc_->signaling_state() == new_state);
state_ = new_state;
}
MediaStreamInterface* RemoteStream(const std::string& label) {
return remote_streams_->find(label);
}
StreamCollectionInterface* remote_streams() const {
return remote_streams_.get();
}
void OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) override {
last_added_stream_ = stream;
remote_streams_->AddStream(stream);
}
void OnRemoveStream(
rtc::scoped_refptr<MediaStreamInterface> stream) override {
last_removed_stream_ = stream;
remote_streams_->RemoveStream(stream.get());
}
void OnRenegotiationNeeded() override { renegotiation_needed_ = true; }
void OnNegotiationNeededEvent(uint32_t event_id) override {
latest_negotiation_needed_event_ = event_id;
}
void OnDataChannel(
rtc::scoped_refptr<DataChannelInterface> data_channel) override {
last_datachannel_ = data_channel;
}
void OnIceConnectionChange(
PeerConnectionInterface::IceConnectionState new_state) override {
RTC_DCHECK(pc_);
RTC_DCHECK(pc_->ice_connection_state() == new_state);
// When ICE is finished, the caller will get to a kIceConnectionCompleted
// state, because it has the ICE controlling role, while the callee
// will get to a kIceConnectionConnected state. This means that both ICE
// and DTLS are connected.
ice_connected_ =
(new_state == PeerConnectionInterface::kIceConnectionConnected) ||
(new_state == PeerConnectionInterface::kIceConnectionCompleted);
callback_triggered_ = true;
}
void OnIceGatheringChange(
PeerConnectionInterface::IceGatheringState new_state) override {
RTC_DCHECK(pc_);
RTC_DCHECK(pc_->ice_gathering_state() == new_state);
ice_gathering_complete_ =
new_state == PeerConnectionInterface::kIceGatheringComplete;
callback_triggered_ = true;
}
void OnIceCandidate(const IceCandidateInterface* candidate) override {
RTC_DCHECK(pc_);
candidates_.push_back(std::make_unique<JsepIceCandidate>(
candidate->sdp_mid(), candidate->sdp_mline_index(),
candidate->candidate()));
callback_triggered_ = true;
}
void OnIceCandidatesRemoved(
const std::vector<cricket::Candidate>& candidates) override {
num_candidates_removed_++;
callback_triggered_ = true;
}
void OnIceConnectionReceivingChange(bool receiving) override {
callback_triggered_ = true;
}
void OnAddTrack(rtc::scoped_refptr<RtpReceiverInterface> receiver,
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
streams) override {
RTC_DCHECK(receiver);
num_added_tracks_++;
last_added_track_label_ = receiver->id();
add_track_events_.push_back(AddTrackEvent(receiver, streams));
}
void OnTrack(
rtc::scoped_refptr<RtpTransceiverInterface> transceiver) override {
on_track_transceivers_.push_back(transceiver);
}
void OnRemoveTrack(
rtc::scoped_refptr<RtpReceiverInterface> receiver) override {
remove_track_events_.push_back(receiver);
}
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetAddTrackReceivers() {
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> receivers;
for (const AddTrackEvent& event : add_track_events_) {
receivers.push_back(event.receiver);
}
return receivers;
}
int CountAddTrackEventsForStream(const std::string& stream_id) {
int found_tracks = 0;
for (const AddTrackEvent& event : add_track_events_) {
bool has_stream_id = false;
for (auto stream : event.streams) {
if (stream->id() == stream_id) {
has_stream_id = true;
break;
}
}
if (has_stream_id) {
++found_tracks;
}
}
return found_tracks;
}
// Returns the id of the last added stream.
// Empty string if no stream have been added.
std::string GetLastAddedStreamId() {
if (last_added_stream_.get())
return last_added_stream_->id();
return "";
}
std::string GetLastRemovedStreamId() {
if (last_removed_stream_.get())
return last_removed_stream_->id();
return "";
}
IceCandidateInterface* last_candidate() {
if (candidates_.empty()) {
return nullptr;
} else {
return candidates_.back().get();
}
}
std::vector<const IceCandidateInterface*> GetAllCandidates() {
std::vector<const IceCandidateInterface*> candidates;
for (const auto& candidate : candidates_) {
candidates.push_back(candidate.get());
}
return candidates;
}
std::vector<IceCandidateInterface*> GetCandidatesByMline(int mline_index) {
std::vector<IceCandidateInterface*> candidates;
for (const auto& candidate : candidates_) {
if (candidate->sdp_mline_index() == mline_index) {
candidates.push_back(candidate.get());
}
}
return candidates;
}
bool legacy_renegotiation_needed() const { return renegotiation_needed_; }
void clear_legacy_renegotiation_needed() { renegotiation_needed_ = false; }
bool has_negotiation_needed_event() {
return latest_negotiation_needed_event_.has_value();
}
uint32_t latest_negotiation_needed_event() {
return latest_negotiation_needed_event_.value_or(0u);
}
void clear_latest_negotiation_needed_event() {
latest_negotiation_needed_event_ = absl::nullopt;
}
rtc::scoped_refptr<PeerConnectionInterface> pc_;
PeerConnectionInterface::SignalingState state_;
std::vector<std::unique_ptr<IceCandidateInterface>> candidates_;
rtc::scoped_refptr<DataChannelInterface> last_datachannel_;
rtc::scoped_refptr<StreamCollection> remote_streams_;
bool renegotiation_needed_ = false;
absl::optional<uint32_t> latest_negotiation_needed_event_;
bool ice_gathering_complete_ = false;
bool ice_connected_ = false;
bool callback_triggered_ = false;
int num_added_tracks_ = 0;
std::string last_added_track_label_;
std::vector<AddTrackEvent> add_track_events_;
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> remove_track_events_;
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
on_track_transceivers_;
int num_candidates_removed_ = 0;
private:
rtc::scoped_refptr<MediaStreamInterface> last_added_stream_;
rtc::scoped_refptr<MediaStreamInterface> last_removed_stream_;
};
class MockCreateSessionDescriptionObserver
: public CreateSessionDescriptionObserver {
public:
MockCreateSessionDescriptionObserver()
: called_(false),
error_("MockCreateSessionDescriptionObserver not called") {}
virtual ~MockCreateSessionDescriptionObserver() {}
void OnSuccess(SessionDescriptionInterface* desc) override {
MutexLock lock(&mutex_);
called_ = true;
error_ = "";
desc_.reset(desc);
}
void OnFailure(RTCError error) override {
MutexLock lock(&mutex_);
called_ = true;
error_ = error.message();
}
bool called() const {
MutexLock lock(&mutex_);
return called_;
}
bool result() const {
MutexLock lock(&mutex_);
return error_.empty();
}
const std::string& error() const {
MutexLock lock(&mutex_);
return error_;
}
std::unique_ptr<SessionDescriptionInterface> MoveDescription() {
MutexLock lock(&mutex_);
return std::move(desc_);
}
private:
mutable Mutex mutex_;
bool called_ RTC_GUARDED_BY(mutex_);
std::string error_ RTC_GUARDED_BY(mutex_);
std::unique_ptr<SessionDescriptionInterface> desc_ RTC_GUARDED_BY(mutex_);
};
class MockSetSessionDescriptionObserver : public SetSessionDescriptionObserver {
public:
static rtc::scoped_refptr<MockSetSessionDescriptionObserver> Create() {
return rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
}
MockSetSessionDescriptionObserver()
: called_(false),
error_("MockSetSessionDescriptionObserver not called") {}
~MockSetSessionDescriptionObserver() override {}
void OnSuccess() override {
MutexLock lock(&mutex_);
called_ = true;
error_ = "";
}
void OnFailure(RTCError error) override {
MutexLock lock(&mutex_);
called_ = true;
error_ = error.message();
}
bool called() const {
MutexLock lock(&mutex_);
return called_;
}
bool result() const {
MutexLock lock(&mutex_);
return error_.empty();
}
const std::string& error() const {
MutexLock lock(&mutex_);
return error_;
}
private:
mutable Mutex mutex_;
bool called_;
std::string error_;
};
class FakeSetLocalDescriptionObserver
: public SetLocalDescriptionObserverInterface {
public:
bool called() const { return error_.has_value(); }
RTCError& error() {
RTC_DCHECK(error_.has_value());
return *error_;
}
// SetLocalDescriptionObserverInterface implementation.
void OnSetLocalDescriptionComplete(RTCError error) override {
error_ = std::move(error);
}
private:
// Set on complete, on success this is set to an RTCError::OK() error.
absl::optional<RTCError> error_;
};
class FakeSetRemoteDescriptionObserver
: public SetRemoteDescriptionObserverInterface {
public:
bool called() const { return error_.has_value(); }
RTCError& error() {
RTC_DCHECK(error_.has_value());
return *error_;
}
// SetRemoteDescriptionObserverInterface implementation.
void OnSetRemoteDescriptionComplete(RTCError error) override {
error_ = std::move(error);
}
private:
// Set on complete, on success this is set to an RTCError::OK() error.
absl::optional<RTCError> error_;
};
class MockDataChannelObserver : public DataChannelObserver {
public:
struct Message {
std::string data;
bool binary;
};
explicit MockDataChannelObserver(DataChannelInterface* channel)
: channel_(channel) {
channel_->RegisterObserver(this);
states_.push_back(channel_->state());
}
virtual ~MockDataChannelObserver() { channel_->UnregisterObserver(); }
void OnBufferedAmountChange(uint64_t previous_amount) override {}
void OnStateChange() override { states_.push_back(channel_->state()); }
void OnMessage(const DataBuffer& buffer) override {
messages_.push_back(
{std::string(buffer.data.data<char>(), buffer.data.size()),
buffer.binary});
}
bool IsOpen() const { return state() == DataChannelInterface::kOpen; }
std::vector<Message> messages() const { return messages_; }
std::string last_message() const {
if (messages_.empty())
return {};
return messages_.back().data;
}
bool last_message_is_binary() const {
if (messages_.empty())
return false;
return messages_.back().binary;
}
size_t received_message_count() const { return messages_.size(); }
DataChannelInterface::DataState state() const { return states_.back(); }
const std::vector<DataChannelInterface::DataState>& states() const {
return states_;
}
private:
rtc::scoped_refptr<DataChannelInterface> channel_;
std::vector<DataChannelInterface::DataState> states_;
std::vector<Message> messages_;
};
class MockStatsObserver : public StatsObserver {
public:
MockStatsObserver() : called_(false), stats_() {}
virtual ~MockStatsObserver() {}
virtual void OnComplete(const StatsReports& reports) {
RTC_CHECK(!called_);
called_ = true;
stats_.Clear();
stats_.number_of_reports = reports.size();
for (const auto* r : reports) {
if (r->type() == StatsReport::kStatsReportTypeSsrc) {
stats_.timestamp = r->timestamp();
GetIntValue(r, StatsReport::kStatsValueNameAudioOutputLevel,
&stats_.audio_output_level);
GetIntValue(r, StatsReport::kStatsValueNameAudioInputLevel,
&stats_.audio_input_level);
GetIntValue(r, StatsReport::kStatsValueNameBytesReceived,
&stats_.bytes_received);
GetIntValue(r, StatsReport::kStatsValueNameBytesSent,
&stats_.bytes_sent);
GetInt64Value(r, StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
&stats_.capture_start_ntp_time);
stats_.track_ids.emplace_back();
GetStringValue(r, StatsReport::kStatsValueNameTrackId,
&stats_.track_ids.back());
} else if (r->type() == StatsReport::kStatsReportTypeBwe) {
stats_.timestamp = r->timestamp();
GetIntValue(r, StatsReport::kStatsValueNameAvailableReceiveBandwidth,
&stats_.available_receive_bandwidth);
} else if (r->type() == StatsReport::kStatsReportTypeComponent) {
stats_.timestamp = r->timestamp();
GetStringValue(r, StatsReport::kStatsValueNameDtlsCipher,
&stats_.dtls_cipher);
GetStringValue(r, StatsReport::kStatsValueNameSrtpCipher,
&stats_.srtp_cipher);
}
}
}
bool called() const { return called_; }
size_t number_of_reports() const { return stats_.number_of_reports; }
double timestamp() const { return stats_.timestamp; }
int AudioOutputLevel() const {
RTC_CHECK(called_);
return stats_.audio_output_level;
}
int AudioInputLevel() const {
RTC_CHECK(called_);
return stats_.audio_input_level;
}
int BytesReceived() const {
RTC_CHECK(called_);
return stats_.bytes_received;
}
int BytesSent() const {
RTC_CHECK(called_);
return stats_.bytes_sent;
}
int64_t CaptureStartNtpTime() const {
RTC_CHECK(called_);
return stats_.capture_start_ntp_time;
}
int AvailableReceiveBandwidth() const {
RTC_CHECK(called_);
return stats_.available_receive_bandwidth;
}
std::string DtlsCipher() const {
RTC_CHECK(called_);
return stats_.dtls_cipher;
}
std::string SrtpCipher() const {
RTC_CHECK(called_);
return stats_.srtp_cipher;
}
std::vector<std::string> TrackIds() const {
RTC_CHECK(called_);
return stats_.track_ids;
}
private:
bool GetIntValue(const StatsReport* report,
StatsReport::StatsValueName name,
int* value) {
const StatsReport::Value* v = report->FindValue(name);
if (v) {
// TODO(tommi): We should really just be using an int here :-/
*value = rtc::FromString<int>(v->ToString());
}
return v != nullptr;
}
bool GetInt64Value(const StatsReport* report,
StatsReport::StatsValueName name,
int64_t* value) {
const StatsReport::Value* v = report->FindValue(name);
if (v) {
// TODO(tommi): We should really just be using an int here :-/
*value = rtc::FromString<int64_t>(v->ToString());
}
return v != nullptr;
}
bool GetStringValue(const StatsReport* report,
StatsReport::StatsValueName name,
std::string* value) {
const StatsReport::Value* v = report->FindValue(name);
if (v)
*value = v->ToString();
return v != nullptr;
}
bool called_;
struct {
void Clear() {
number_of_reports = 0;
timestamp = 0;
audio_output_level = 0;
audio_input_level = 0;
bytes_received = 0;
bytes_sent = 0;
capture_start_ntp_time = 0;
available_receive_bandwidth = 0;
dtls_cipher.clear();
srtp_cipher.clear();
track_ids.clear();
}
size_t number_of_reports;
double timestamp;
int audio_output_level;
int audio_input_level;
int bytes_received;
int bytes_sent;
int64_t capture_start_ntp_time;
int available_receive_bandwidth;
std::string dtls_cipher;
std::string srtp_cipher;
std::vector<std::string> track_ids;
} stats_;
};
// Helper class that just stores the report from the callback.
class MockRTCStatsCollectorCallback : public RTCStatsCollectorCallback {
public:
rtc::scoped_refptr<const RTCStatsReport> report() { return report_; }
bool called() const { return called_; }
protected:
void OnStatsDelivered(
const rtc::scoped_refptr<const RTCStatsReport>& report) override {
report_ = report;
called_ = true;
}
private:
bool called_ = false;
rtc::scoped_refptr<const RTCStatsReport> report_;
};
} // namespace webrtc
#endif // PC_TEST_MOCK_PEER_CONNECTION_OBSERVERS_H_

View file

@ -0,0 +1,82 @@
/*
* Copyright 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 PC_TEST_MOCK_RTP_RECEIVER_INTERNAL_H_
#define PC_TEST_MOCK_RTP_RECEIVER_INTERNAL_H_
#include <string>
#include <vector>
#include "absl/types/optional.h"
#include "pc/rtp_receiver.h"
#include "test/gmock.h"
namespace webrtc {
// The definition of MockRtpReceiver is copied in to avoid multiple inheritance.
class MockRtpReceiverInternal : public RtpReceiverInternal {
public:
// RtpReceiverInterface methods.
MOCK_METHOD(rtc::scoped_refptr<MediaStreamTrackInterface>,
track,
(),
(const, override));
MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>,
dtls_transport,
(),
(const, override));
MOCK_METHOD(std::vector<std::string>, stream_ids, (), (const, override));
MOCK_METHOD(std::vector<rtc::scoped_refptr<MediaStreamInterface>>,
streams,
(),
(const, override));
MOCK_METHOD(cricket::MediaType, media_type, (), (const, override));
MOCK_METHOD(std::string, id, (), (const, override));
MOCK_METHOD(RtpParameters, GetParameters, (), (const, override));
MOCK_METHOD(void, SetObserver, (RtpReceiverObserverInterface*), (override));
MOCK_METHOD(void,
SetJitterBufferMinimumDelay,
(absl::optional<double>),
(override));
MOCK_METHOD(std::vector<RtpSource>, GetSources, (), (const, override));
MOCK_METHOD(void,
SetFrameDecryptor,
(rtc::scoped_refptr<FrameDecryptorInterface>),
(override));
MOCK_METHOD(rtc::scoped_refptr<FrameDecryptorInterface>,
GetFrameDecryptor,
(),
(const, override));
// RtpReceiverInternal methods.
MOCK_METHOD(void, Stop, (), (override));
MOCK_METHOD(void,
SetMediaChannel,
(cricket::MediaReceiveChannelInterface*),
(override));
MOCK_METHOD(void, SetupMediaChannel, (uint32_t), (override));
MOCK_METHOD(void, SetupUnsignaledMediaChannel, (), (override));
MOCK_METHOD(absl::optional<uint32_t>, ssrc, (), (const, override));
MOCK_METHOD(void, NotifyFirstPacketReceived, (), (override));
MOCK_METHOD(void, set_stream_ids, (std::vector<std::string>), (override));
MOCK_METHOD(void,
set_transport,
(rtc::scoped_refptr<DtlsTransportInterface>),
(override));
MOCK_METHOD(void,
SetStreams,
(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&),
(override));
MOCK_METHOD(int, AttachmentId, (), (const, override));
};
} // namespace webrtc
#endif // PC_TEST_MOCK_RTP_RECEIVER_INTERNAL_H_

View file

@ -0,0 +1,112 @@
/*
* Copyright 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 PC_TEST_MOCK_RTP_SENDER_INTERNAL_H_
#define PC_TEST_MOCK_RTP_SENDER_INTERNAL_H_
#include <memory>
#include <string>
#include <vector>
#include "pc/rtp_sender.h"
#include "test/gmock.h"
namespace webrtc {
// The definition of MockRtpSender is copied in to avoid multiple inheritance.
class MockRtpSenderInternal : public RtpSenderInternal {
public:
// RtpSenderInterface methods.
MOCK_METHOD(bool, SetTrack, (MediaStreamTrackInterface*), (override));
MOCK_METHOD(rtc::scoped_refptr<MediaStreamTrackInterface>,
track,
(),
(const, override));
MOCK_METHOD(uint32_t, ssrc, (), (const, override));
MOCK_METHOD(rtc::scoped_refptr<DtlsTransportInterface>,
dtls_transport,
(),
(const, override));
MOCK_METHOD(cricket::MediaType, media_type, (), (const, override));
MOCK_METHOD(std::string, id, (), (const, override));
MOCK_METHOD(std::vector<std::string>, stream_ids, (), (const, override));
MOCK_METHOD(std::vector<RtpEncodingParameters>,
init_send_encodings,
(),
(const, override));
MOCK_METHOD(void,
set_transport,
(rtc::scoped_refptr<DtlsTransportInterface>),
(override));
MOCK_METHOD(RtpParameters, GetParameters, (), (const, override));
MOCK_METHOD(RtpParameters, GetParametersInternal, (), (const, override));
MOCK_METHOD(RtpParameters,
GetParametersInternalWithAllLayers,
(),
(const, override));
MOCK_METHOD(RTCError, SetParameters, (const RtpParameters&), (override));
MOCK_METHOD(void,
SetParametersAsync,
(const RtpParameters&, SetParametersCallback),
(override));
MOCK_METHOD(void,
SetParametersInternal,
(const RtpParameters&, SetParametersCallback, bool blocking),
(override));
MOCK_METHOD(RTCError,
SetParametersInternalWithAllLayers,
(const RtpParameters&),
(override));
MOCK_METHOD(RTCError,
CheckCodecParameters,
(const RtpParameters&),
(override));
MOCK_METHOD(void,
SetCodecPreferences,
(std::vector<cricket::VideoCodec>),
(override));
MOCK_METHOD(rtc::scoped_refptr<DtmfSenderInterface>,
GetDtmfSender,
(),
(const, override));
MOCK_METHOD(void,
SetFrameEncryptor,
(rtc::scoped_refptr<FrameEncryptorInterface>),
(override));
MOCK_METHOD(rtc::scoped_refptr<FrameEncryptorInterface>,
GetFrameEncryptor,
(),
(const, override));
MOCK_METHOD(void,
SetEncoderToPacketizerFrameTransformer,
(rtc::scoped_refptr<FrameTransformerInterface>),
(override));
MOCK_METHOD(void,
SetEncoderSelector,
(std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface>),
(override));
// RtpSenderInternal methods.
MOCK_METHOD1(SetMediaChannel, void(cricket::MediaSendChannelInterface*));
MOCK_METHOD1(SetSsrc, void(uint32_t));
MOCK_METHOD1(set_stream_ids, void(const std::vector<std::string>&));
MOCK_METHOD1(SetStreams, void(const std::vector<std::string>&));
MOCK_METHOD1(set_init_send_encodings,
void(const std::vector<RtpEncodingParameters>&));
MOCK_METHOD0(Stop, void());
MOCK_CONST_METHOD0(AttachmentId, int());
MOCK_METHOD1(DisableEncodingLayers,
RTCError(const std::vector<std::string>&));
MOCK_METHOD0(SetTransceiverAsStopped, void());
};
} // namespace webrtc
#endif // PC_TEST_MOCK_RTP_SENDER_INTERNAL_H_

View file

@ -0,0 +1,130 @@
/*
* Copyright 2023 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 PC_TEST_MOCK_VOICE_MEDIA_RECEIVE_CHANNEL_INTERFACE_H_
#define PC_TEST_MOCK_VOICE_MEDIA_RECEIVE_CHANNEL_INTERFACE_H_
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "api/call/audio_sink.h"
#include "media/base/media_channel.h"
#include "media/base/media_channel_impl.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/gunit.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace cricket {
class MockVoiceMediaReceiveChannelInterface
: public VoiceMediaReceiveChannelInterface {
public:
MockVoiceMediaReceiveChannelInterface() {
ON_CALL(*this, AsVoiceReceiveChannel).WillByDefault(testing::Return(this));
}
// VoiceMediaReceiveChannelInterface
MOCK_METHOD(bool,
SetReceiverParameters,
(const AudioReceiverParameters& params),
(override));
MOCK_METHOD(webrtc::RtpParameters,
GetRtpReceiverParameters,
(uint32_t ssrc),
(const, override));
MOCK_METHOD(std::vector<webrtc::RtpSource>,
GetSources,
(uint32_t ssrc),
(const, override));
MOCK_METHOD(webrtc::RtpParameters,
GetDefaultRtpReceiveParameters,
(),
(const, override));
MOCK_METHOD(void, SetPlayout, (bool playout), (override));
MOCK_METHOD(bool,
SetOutputVolume,
(uint32_t ssrc, double volume),
(override));
MOCK_METHOD(bool, SetDefaultOutputVolume, (double volume), (override));
MOCK_METHOD(void,
SetRawAudioSink,
(uint32_t ssrc, std::unique_ptr<webrtc::AudioSinkInterface> sink),
(override));
MOCK_METHOD(void,
SetDefaultRawAudioSink,
(std::unique_ptr<webrtc::AudioSinkInterface> sink),
(override));
MOCK_METHOD(bool,
GetStats,
(VoiceMediaReceiveInfo * stats, bool reset_legacy),
(override));
MOCK_METHOD(void, SetReceiveNackEnabled, (bool enabled), (override));
MOCK_METHOD(void, SetReceiveNonSenderRttEnabled, (bool enabled), (override));
// MediaReceiveChannelInterface
MOCK_METHOD(VideoMediaReceiveChannelInterface*,
AsVideoReceiveChannel,
(),
(override));
MOCK_METHOD(VoiceMediaReceiveChannelInterface*,
AsVoiceReceiveChannel,
(),
(override));
MOCK_METHOD(cricket::MediaType, media_type, (), (const, override));
MOCK_METHOD(bool, AddRecvStream, (const StreamParams& sp), (override));
MOCK_METHOD(bool, RemoveRecvStream, (uint32_t ssrc), (override));
MOCK_METHOD(void, ResetUnsignaledRecvStream, (), (override));
MOCK_METHOD(void,
SetInterface,
(MediaChannelNetworkInterface * iface),
(override));
MOCK_METHOD(void,
OnPacketReceived,
(const webrtc::RtpPacketReceived& packet),
(override));
MOCK_METHOD(absl::optional<uint32_t>,
GetUnsignaledSsrc,
(),
(const, override));
MOCK_METHOD(void,
ChooseReceiverReportSsrc,
(const std::set<uint32_t>& choices),
(override));
MOCK_METHOD(void, OnDemuxerCriteriaUpdatePending, (), (override));
MOCK_METHOD(void, OnDemuxerCriteriaUpdateComplete, (), (override));
MOCK_METHOD(
void,
SetFrameDecryptor,
(uint32_t ssrc,
rtc::scoped_refptr<webrtc::FrameDecryptorInterface> frame_decryptor),
(override));
MOCK_METHOD(
void,
SetDepacketizerToDecoderFrameTransformer,
(uint32_t ssrc,
rtc::scoped_refptr<webrtc::FrameTransformerInterface> frame_transformer),
(override));
MOCK_METHOD(bool,
SetBaseMinimumPlayoutDelayMs,
(uint32_t ssrc, int delay_ms),
(override));
MOCK_METHOD(absl::optional<int>,
GetBaseMinimumPlayoutDelayMs,
(uint32_t ssrc),
(const, override));
};
static_assert(!std::is_abstract_v<MockVoiceMediaReceiveChannelInterface>, "");
} // namespace cricket
#endif // PC_TEST_MOCK_VOICE_MEDIA_RECEIVE_CHANNEL_INTERFACE_H_

View file

@ -0,0 +1,429 @@
/*
* Copyright 2013 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 "pc/test/peer_connection_test_wrapper.h"
#include <stddef.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/strings/match.h"
#include "absl/types/optional.h"
#include "api/audio/audio_mixer.h"
#include "api/create_peerconnection_factory.h"
#include "api/media_types.h"
#include "api/sequence_checker.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "api/video_codecs/video_decoder_factory_template.h"
#include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h"
#include "api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h"
#include "api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h"
#include "api/video_codecs/video_decoder_factory_template_open_h264_adapter.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "api/video_codecs/video_encoder_factory_template.h"
#include "api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h"
#include "api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h"
#include "api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h"
#include "api/video_codecs/video_encoder_factory_template_open_h264_adapter.h"
#include "media/engine/simulcast_encoder_adapter.h"
#include "modules/audio_device/include/audio_device.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "p2p/base/fake_port_allocator.h"
#include "p2p/base/port_allocator.h"
#include "pc/test/fake_periodic_video_source.h"
#include "pc/test/fake_rtc_certificate_generator.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/gunit.h"
#include "rtc_base/logging.h"
#include "rtc_base/rtc_certificate_generator.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/time_utils.h"
#include "test/gtest.h"
using webrtc::FakeVideoTrackRenderer;
using webrtc::IceCandidateInterface;
using webrtc::MediaStreamInterface;
using webrtc::MediaStreamTrackInterface;
using webrtc::MockSetSessionDescriptionObserver;
using webrtc::PeerConnectionInterface;
using webrtc::RtpReceiverInterface;
using webrtc::SdpType;
using webrtc::SessionDescriptionInterface;
using webrtc::VideoTrackInterface;
namespace {
const char kStreamIdBase[] = "stream_id";
const char kVideoTrackLabelBase[] = "video_track";
const char kAudioTrackLabelBase[] = "audio_track";
constexpr int kMaxWait = 10000;
constexpr int kTestAudioFrameCount = 3;
constexpr int kTestVideoFrameCount = 3;
class FuzzyMatchedVideoEncoderFactory : public webrtc::VideoEncoderFactory {
public:
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
return factory_.GetSupportedFormats();
}
std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(
const webrtc::SdpVideoFormat& format) override {
if (absl::optional<webrtc::SdpVideoFormat> original_format =
webrtc::FuzzyMatchSdpVideoFormat(factory_.GetSupportedFormats(),
format)) {
return std::make_unique<webrtc::SimulcastEncoderAdapter>(
&factory_, *original_format);
}
return nullptr;
}
CodecSupport QueryCodecSupport(
const webrtc::SdpVideoFormat& format,
absl::optional<std::string> scalability_mode) const override {
return factory_.QueryCodecSupport(format, scalability_mode);
}
private:
webrtc::VideoEncoderFactoryTemplate<webrtc::LibvpxVp8EncoderTemplateAdapter,
webrtc::LibvpxVp9EncoderTemplateAdapter,
webrtc::OpenH264EncoderTemplateAdapter,
webrtc::LibaomAv1EncoderTemplateAdapter>
factory_;
};
} // namespace
void PeerConnectionTestWrapper::Connect(PeerConnectionTestWrapper* caller,
PeerConnectionTestWrapper* callee) {
caller->SignalOnIceCandidateReady.connect(
callee, &PeerConnectionTestWrapper::AddIceCandidate);
callee->SignalOnIceCandidateReady.connect(
caller, &PeerConnectionTestWrapper::AddIceCandidate);
caller->SignalOnSdpReady.connect(callee,
&PeerConnectionTestWrapper::ReceiveOfferSdp);
callee->SignalOnSdpReady.connect(
caller, &PeerConnectionTestWrapper::ReceiveAnswerSdp);
}
PeerConnectionTestWrapper::PeerConnectionTestWrapper(
const std::string& name,
rtc::SocketServer* socket_server,
rtc::Thread* network_thread,
rtc::Thread* worker_thread)
: name_(name),
socket_server_(socket_server),
network_thread_(network_thread),
worker_thread_(worker_thread),
pending_negotiation_(false) {
pc_thread_checker_.Detach();
}
PeerConnectionTestWrapper::~PeerConnectionTestWrapper() {
RTC_DCHECK_RUN_ON(&pc_thread_checker_);
// To avoid flaky bot failures, make sure fake sources are stopped prior to
// closing the peer connections. See https://crbug.com/webrtc/15018.
StopFakeVideoSources();
// Either network_thread or worker_thread might be active at this point.
// Relying on ~PeerConnection to properly wait for them doesn't work,
// as a vptr race might occur (before we enter the destruction body).
// See: bugs.webrtc.org/9847
if (pc()) {
pc()->Close();
}
}
bool PeerConnectionTestWrapper::CreatePc(
const webrtc::PeerConnectionInterface::RTCConfiguration& config,
rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory,
rtc::scoped_refptr<webrtc::AudioDecoderFactory> audio_decoder_factory) {
std::unique_ptr<cricket::PortAllocator> port_allocator(
new cricket::FakePortAllocator(
network_thread_,
std::make_unique<rtc::BasicPacketSocketFactory>(socket_server_),
&field_trials_));
RTC_DCHECK_RUN_ON(&pc_thread_checker_);
fake_audio_capture_module_ = FakeAudioCaptureModule::Create();
if (fake_audio_capture_module_ == nullptr) {
return false;
}
peer_connection_factory_ = webrtc::CreatePeerConnectionFactory(
network_thread_, worker_thread_, rtc::Thread::Current(),
rtc::scoped_refptr<webrtc::AudioDeviceModule>(fake_audio_capture_module_),
audio_encoder_factory, audio_decoder_factory,
std::make_unique<FuzzyMatchedVideoEncoderFactory>(),
std::make_unique<webrtc::VideoDecoderFactoryTemplate<
webrtc::LibvpxVp8DecoderTemplateAdapter,
webrtc::LibvpxVp9DecoderTemplateAdapter,
webrtc::OpenH264DecoderTemplateAdapter,
webrtc::Dav1dDecoderTemplateAdapter>>(),
nullptr /* audio_mixer */, nullptr /* audio_processing */);
if (!peer_connection_factory_) {
return false;
}
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator(
new FakeRTCCertificateGenerator());
webrtc::PeerConnectionDependencies deps(this);
deps.allocator = std::move(port_allocator);
deps.cert_generator = std::move(cert_generator);
auto result = peer_connection_factory_->CreatePeerConnectionOrError(
config, std::move(deps));
if (result.ok()) {
peer_connection_ = result.MoveValue();
return true;
} else {
return false;
}
}
rtc::scoped_refptr<webrtc::DataChannelInterface>
PeerConnectionTestWrapper::CreateDataChannel(
const std::string& label,
const webrtc::DataChannelInit& init) {
auto result = peer_connection_->CreateDataChannelOrError(label, &init);
if (!result.ok()) {
RTC_LOG(LS_ERROR) << "CreateDataChannel failed: "
<< ToString(result.error().type()) << " "
<< result.error().message();
return nullptr;
}
return result.MoveValue();
}
absl::optional<webrtc::RtpCodecCapability>
PeerConnectionTestWrapper::FindFirstSendCodecWithName(
cricket::MediaType media_type,
const std::string& name) const {
std::vector<webrtc::RtpCodecCapability> codecs =
peer_connection_factory_->GetRtpSenderCapabilities(media_type).codecs;
for (const auto& codec : codecs) {
if (absl::EqualsIgnoreCase(codec.name, name)) {
return codec;
}
}
return absl::nullopt;
}
void PeerConnectionTestWrapper::WaitForNegotiation() {
EXPECT_TRUE_WAIT(!pending_negotiation_, kMaxWait);
}
void PeerConnectionTestWrapper::OnSignalingChange(
webrtc::PeerConnectionInterface::SignalingState new_state) {
if (new_state == webrtc::PeerConnectionInterface::SignalingState::kStable) {
pending_negotiation_ = false;
}
}
void PeerConnectionTestWrapper::OnAddTrack(
rtc::scoped_refptr<RtpReceiverInterface> receiver,
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": OnAddTrack";
if (receiver->track()->kind() == MediaStreamTrackInterface::kVideoKind) {
auto* video_track =
static_cast<VideoTrackInterface*>(receiver->track().get());
renderer_ = std::make_unique<FakeVideoTrackRenderer>(video_track);
}
}
void PeerConnectionTestWrapper::OnIceCandidate(
const IceCandidateInterface* candidate) {
std::string sdp;
EXPECT_TRUE(candidate->ToString(&sdp));
SignalOnIceCandidateReady(candidate->sdp_mid(), candidate->sdp_mline_index(),
sdp);
}
void PeerConnectionTestWrapper::OnDataChannel(
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
SignalOnDataChannel(data_channel.get());
}
void PeerConnectionTestWrapper::OnSuccess(SessionDescriptionInterface* desc) {
// This callback should take the ownership of `desc`.
std::unique_ptr<SessionDescriptionInterface> owned_desc(desc);
std::string sdp;
EXPECT_TRUE(desc->ToString(&sdp));
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": "
<< webrtc::SdpTypeToString(desc->GetType())
<< " sdp created: " << sdp;
SetLocalDescription(desc->GetType(), sdp);
SignalOnSdpReady(sdp);
}
void PeerConnectionTestWrapper::CreateOffer(
const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions& options) {
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": CreateOffer.";
pending_negotiation_ = true;
peer_connection_->CreateOffer(this, options);
}
void PeerConnectionTestWrapper::CreateAnswer(
const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions& options) {
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": CreateAnswer.";
pending_negotiation_ = true;
peer_connection_->CreateAnswer(this, options);
}
void PeerConnectionTestWrapper::ReceiveOfferSdp(const std::string& sdp) {
SetRemoteDescription(SdpType::kOffer, sdp);
CreateAnswer(webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
}
void PeerConnectionTestWrapper::ReceiveAnswerSdp(const std::string& sdp) {
SetRemoteDescription(SdpType::kAnswer, sdp);
}
void PeerConnectionTestWrapper::SetLocalDescription(SdpType type,
const std::string& sdp) {
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": SetLocalDescription " << webrtc::SdpTypeToString(type)
<< " " << sdp;
auto observer = rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
peer_connection_->SetLocalDescription(
observer.get(), webrtc::CreateSessionDescription(type, sdp).release());
}
void PeerConnectionTestWrapper::SetRemoteDescription(SdpType type,
const std::string& sdp) {
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": SetRemoteDescription " << webrtc::SdpTypeToString(type)
<< " " << sdp;
auto observer = rtc::make_ref_counted<MockSetSessionDescriptionObserver>();
peer_connection_->SetRemoteDescription(
observer.get(), webrtc::CreateSessionDescription(type, sdp).release());
}
void PeerConnectionTestWrapper::AddIceCandidate(const std::string& sdp_mid,
int sdp_mline_index,
const std::string& candidate) {
std::unique_ptr<webrtc::IceCandidateInterface> owned_candidate(
webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, candidate, NULL));
EXPECT_TRUE(peer_connection_->AddIceCandidate(owned_candidate.get()));
}
void PeerConnectionTestWrapper::WaitForCallEstablished() {
WaitForConnection();
WaitForAudio();
WaitForVideo();
}
void PeerConnectionTestWrapper::WaitForConnection() {
EXPECT_TRUE_WAIT(CheckForConnection(), kMaxWait);
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_ << ": Connected.";
}
bool PeerConnectionTestWrapper::CheckForConnection() {
return (peer_connection_->ice_connection_state() ==
PeerConnectionInterface::kIceConnectionConnected) ||
(peer_connection_->ice_connection_state() ==
PeerConnectionInterface::kIceConnectionCompleted);
}
void PeerConnectionTestWrapper::WaitForAudio() {
EXPECT_TRUE_WAIT(CheckForAudio(), kMaxWait);
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": Got enough audio frames.";
}
bool PeerConnectionTestWrapper::CheckForAudio() {
return (fake_audio_capture_module_->frames_received() >=
kTestAudioFrameCount);
}
void PeerConnectionTestWrapper::WaitForVideo() {
EXPECT_TRUE_WAIT(CheckForVideo(), kMaxWait);
RTC_LOG(LS_INFO) << "PeerConnectionTestWrapper " << name_
<< ": Got enough video frames.";
}
bool PeerConnectionTestWrapper::CheckForVideo() {
if (!renderer_) {
return false;
}
return (renderer_->num_rendered_frames() >= kTestVideoFrameCount);
}
void PeerConnectionTestWrapper::GetAndAddUserMedia(
bool audio,
const cricket::AudioOptions& audio_options,
bool video) {
rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
GetUserMedia(audio, audio_options, video);
for (const auto& audio_track : stream->GetAudioTracks()) {
EXPECT_TRUE(peer_connection_->AddTrack(audio_track, {stream->id()}).ok());
}
for (const auto& video_track : stream->GetVideoTracks()) {
EXPECT_TRUE(peer_connection_->AddTrack(video_track, {stream->id()}).ok());
}
}
rtc::scoped_refptr<webrtc::MediaStreamInterface>
PeerConnectionTestWrapper::GetUserMedia(
bool audio,
const cricket::AudioOptions& audio_options,
bool video,
webrtc::Resolution resolution) {
std::string stream_id =
kStreamIdBase + rtc::ToString(num_get_user_media_calls_++);
rtc::scoped_refptr<webrtc::MediaStreamInterface> stream =
peer_connection_factory_->CreateLocalMediaStream(stream_id);
if (audio) {
cricket::AudioOptions options = audio_options;
// Disable highpass filter so that we can get all the test audio frames.
options.highpass_filter = false;
rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
peer_connection_factory_->CreateAudioSource(options);
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
peer_connection_factory_->CreateAudioTrack(kAudioTrackLabelBase,
source.get()));
stream->AddTrack(audio_track);
}
if (video) {
// Set max frame rate to 10fps to reduce the risk of the tests to be flaky.
webrtc::FakePeriodicVideoSource::Config config;
config.frame_interval_ms = 100;
config.timestamp_offset_ms = rtc::TimeMillis();
config.width = resolution.width;
config.height = resolution.height;
auto source = rtc::make_ref_counted<webrtc::FakePeriodicVideoTrackSource>(
config, /* remote */ false);
fake_video_sources_.push_back(source);
std::string videotrack_label = stream_id + kVideoTrackLabelBase;
rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
peer_connection_factory_->CreateVideoTrack(source, videotrack_label));
stream->AddTrack(video_track);
}
return stream;
}
void PeerConnectionTestWrapper::StopFakeVideoSources() {
for (const auto& fake_video_source : fake_video_sources_) {
fake_video_source->fake_periodic_source().Stop();
}
fake_video_sources_.clear();
}

View file

@ -0,0 +1,150 @@
/*
* Copyright 2013 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 PC_TEST_PEER_CONNECTION_TEST_WRAPPER_H_
#define PC_TEST_PEER_CONNECTION_TEST_WRAPPER_H_
#include <memory>
#include <string>
#include <vector>
#include "api/audio_codecs/audio_decoder_factory.h"
#include "api/audio_codecs/audio_encoder_factory.h"
#include "api/audio_options.h"
#include "api/data_channel_interface.h"
#include "api/jsep.h"
#include "api/media_stream_interface.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_error.h"
#include "api/rtp_parameters.h"
#include "api/rtp_receiver_interface.h"
#include "api/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "api/video/resolution.h"
#include "pc/test/fake_audio_capture_module.h"
#include "pc/test/fake_periodic_video_source.h"
#include "pc/test/fake_periodic_video_track_source.h"
#include "pc/test/fake_video_track_renderer.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/thread.h"
#include "test/scoped_key_value_config.h"
class PeerConnectionTestWrapper
: public webrtc::PeerConnectionObserver,
public webrtc::CreateSessionDescriptionObserver,
public sigslot::has_slots<> {
public:
static void Connect(PeerConnectionTestWrapper* caller,
PeerConnectionTestWrapper* callee);
PeerConnectionTestWrapper(const std::string& name,
rtc::SocketServer* socket_server,
rtc::Thread* network_thread,
rtc::Thread* worker_thread);
virtual ~PeerConnectionTestWrapper();
bool CreatePc(
const webrtc::PeerConnectionInterface::RTCConfiguration& config,
rtc::scoped_refptr<webrtc::AudioEncoderFactory> audio_encoder_factory,
rtc::scoped_refptr<webrtc::AudioDecoderFactory> audio_decoder_factory);
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory()
const {
return peer_connection_factory_;
}
webrtc::PeerConnectionInterface* pc() { return peer_connection_.get(); }
rtc::scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
const std::string& label,
const webrtc::DataChannelInit& init);
absl::optional<webrtc::RtpCodecCapability> FindFirstSendCodecWithName(
cricket::MediaType media_type,
const std::string& name) const;
void WaitForNegotiation();
// Implements PeerConnectionObserver.
void OnSignalingChange(
webrtc::PeerConnectionInterface::SignalingState new_state) override;
void OnAddTrack(
rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>&
streams) override;
void OnDataChannel(
rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) override;
void OnRenegotiationNeeded() override {}
void OnIceConnectionChange(
webrtc::PeerConnectionInterface::IceConnectionState new_state) override {}
void OnIceGatheringChange(
webrtc::PeerConnectionInterface::IceGatheringState new_state) override {}
void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
// Implements CreateSessionDescriptionObserver.
void OnSuccess(webrtc::SessionDescriptionInterface* desc) override;
void OnFailure(webrtc::RTCError) override {}
void CreateOffer(
const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions& options);
void CreateAnswer(
const webrtc::PeerConnectionInterface::RTCOfferAnswerOptions& options);
void ReceiveOfferSdp(const std::string& sdp);
void ReceiveAnswerSdp(const std::string& sdp);
void AddIceCandidate(const std::string& sdp_mid,
int sdp_mline_index,
const std::string& candidate);
void WaitForCallEstablished();
void WaitForConnection();
void WaitForAudio();
void WaitForVideo();
void GetAndAddUserMedia(bool audio,
const cricket::AudioOptions& audio_options,
bool video);
// sigslots
sigslot::signal3<const std::string&, int, const std::string&>
SignalOnIceCandidateReady;
sigslot::signal1<const std::string&> SignalOnSdpReady;
sigslot::signal1<webrtc::DataChannelInterface*> SignalOnDataChannel;
rtc::scoped_refptr<webrtc::MediaStreamInterface> GetUserMedia(
bool audio,
const cricket::AudioOptions& audio_options,
bool video,
webrtc::Resolution resolution = {
.width = webrtc::FakePeriodicVideoSource::kDefaultWidth,
.height = webrtc::FakePeriodicVideoSource::kDefaultHeight});
void StopFakeVideoSources();
private:
void SetLocalDescription(webrtc::SdpType type, const std::string& sdp);
void SetRemoteDescription(webrtc::SdpType type, const std::string& sdp);
bool CheckForConnection();
bool CheckForAudio();
bool CheckForVideo();
webrtc::test::ScopedKeyValueConfig field_trials_;
std::string name_;
rtc::SocketServer* const socket_server_;
rtc::Thread* const network_thread_;
rtc::Thread* const worker_thread_;
webrtc::SequenceChecker pc_thread_checker_;
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
peer_connection_factory_;
rtc::scoped_refptr<FakeAudioCaptureModule> fake_audio_capture_module_;
std::unique_ptr<webrtc::FakeVideoTrackRenderer> renderer_;
int num_get_user_media_calls_ = 0;
bool pending_negotiation_;
std::vector<rtc::scoped_refptr<webrtc::FakePeriodicVideoTrackSource>>
fake_video_sources_;
};
#endif // PC_TEST_PEER_CONNECTION_TEST_WRAPPER_H_

View file

@ -0,0 +1,55 @@
/*
* Copyright 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 PC_TEST_RTC_STATS_OBTAINER_H_
#define PC_TEST_RTC_STATS_OBTAINER_H_
#include "api/make_ref_counted.h"
#include "api/sequence_checker.h"
#include "api/stats/rtc_stats_collector_callback.h"
#include "api/stats/rtc_stats_report.h"
#include "rtc_base/gunit.h"
namespace webrtc {
class RTCStatsObtainer : public RTCStatsCollectorCallback {
public:
static rtc::scoped_refptr<RTCStatsObtainer> Create(
rtc::scoped_refptr<const RTCStatsReport>* report_ptr = nullptr) {
return rtc::make_ref_counted<RTCStatsObtainer>(report_ptr);
}
void OnStatsDelivered(
const rtc::scoped_refptr<const RTCStatsReport>& report) override {
EXPECT_TRUE(thread_checker_.IsCurrent());
report_ = report;
if (report_ptr_)
*report_ptr_ = report_;
}
rtc::scoped_refptr<const RTCStatsReport> report() const {
EXPECT_TRUE(thread_checker_.IsCurrent());
return report_;
}
protected:
explicit RTCStatsObtainer(
rtc::scoped_refptr<const RTCStatsReport>* report_ptr)
: report_ptr_(report_ptr) {}
private:
SequenceChecker thread_checker_;
rtc::scoped_refptr<const RTCStatsReport> report_;
rtc::scoped_refptr<const RTCStatsReport>* report_ptr_;
};
} // namespace webrtc
#endif // PC_TEST_RTC_STATS_OBTAINER_H_

View file

@ -0,0 +1,109 @@
/*
* Copyright 2017 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 PC_TEST_RTP_TRANSPORT_TEST_UTIL_H_
#define PC_TEST_RTP_TRANSPORT_TEST_UTIL_H_
#include <utility>
#include "call/rtp_packet_sink_interface.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "pc/rtp_transport_internal.h"
namespace webrtc {
// Used to handle the signals when the RtpTransport receives an RTP/RTCP packet.
// Used in Rtp/Srtp/DtlsTransport unit tests.
class TransportObserver : public RtpPacketSinkInterface {
public:
TransportObserver() {}
explicit TransportObserver(RtpTransportInternal* rtp_transport) {
rtp_transport->SubscribeRtcpPacketReceived(
this, [this](rtc::CopyOnWriteBuffer* buffer, int64_t packet_time_ms) {
OnRtcpPacketReceived(buffer, packet_time_ms);
});
rtp_transport->SubscribeReadyToSend(
this, [this](bool arg) { OnReadyToSend(arg); });
rtp_transport->SetUnDemuxableRtpPacketReceivedHandler(
[this](RtpPacketReceived& packet) { OnUndemuxableRtpPacket(packet); });
rtp_transport->SubscribeSentPacket(this,
[this](const rtc::SentPacket& packet) {
sent_packet_count_++;
if (action_on_sent_packet_) {
action_on_sent_packet_();
}
});
}
// RtpPacketInterface override.
void OnRtpPacket(const RtpPacketReceived& packet) override {
rtp_count_++;
last_recv_rtp_packet_ = packet.Buffer();
}
void OnUndemuxableRtpPacket(const RtpPacketReceived& packet) {
un_demuxable_rtp_count_++;
}
void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
int64_t packet_time_us) {
rtcp_count_++;
last_recv_rtcp_packet_ = *packet;
}
int rtp_count() const { return rtp_count_; }
int un_demuxable_rtp_count() const { return un_demuxable_rtp_count_; }
int rtcp_count() const { return rtcp_count_; }
int sent_packet_count() const { return sent_packet_count_; }
rtc::CopyOnWriteBuffer last_recv_rtp_packet() {
return last_recv_rtp_packet_;
}
rtc::CopyOnWriteBuffer last_recv_rtcp_packet() {
return last_recv_rtcp_packet_;
}
void OnReadyToSend(bool ready) {
if (action_on_ready_to_send_) {
action_on_ready_to_send_(ready);
}
ready_to_send_signal_count_++;
ready_to_send_ = ready;
}
bool ready_to_send() { return ready_to_send_; }
int ready_to_send_signal_count() { return ready_to_send_signal_count_; }
void SetActionOnReadyToSend(absl::AnyInvocable<void(bool)> action) {
action_on_ready_to_send_ = std::move(action);
}
void SetActionOnSentPacket(absl::AnyInvocable<void()> action) {
action_on_sent_packet_ = std::move(action);
}
private:
bool ready_to_send_ = false;
int rtp_count_ = 0;
int un_demuxable_rtp_count_ = 0;
int rtcp_count_ = 0;
int sent_packet_count_ = 0;
int ready_to_send_signal_count_ = 0;
rtc::CopyOnWriteBuffer last_recv_rtp_packet_;
rtc::CopyOnWriteBuffer last_recv_rtcp_packet_;
absl::AnyInvocable<void(bool)> action_on_ready_to_send_;
absl::AnyInvocable<void()> action_on_sent_packet_;
};
} // namespace webrtc
#endif // PC_TEST_RTP_TRANSPORT_TEST_UTIL_H_

View file

@ -0,0 +1,55 @@
/*
* Copyright 2023 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 "pc/test/simulcast_layer_util.h"
#include "absl/algorithm/container.h"
#include "rtc_base/checks.h"
namespace webrtc {
std::vector<cricket::SimulcastLayer> CreateLayers(
const std::vector<std::string>& rids,
const std::vector<bool>& active) {
RTC_DCHECK_EQ(rids.size(), active.size());
std::vector<cricket::SimulcastLayer> result;
absl::c_transform(rids, active, std::back_inserter(result),
[](const std::string& rid, bool is_active) {
return cricket::SimulcastLayer(rid, !is_active);
});
return result;
}
std::vector<cricket::SimulcastLayer> CreateLayers(
const std::vector<std::string>& rids,
bool active) {
return CreateLayers(rids, std::vector<bool>(rids.size(), active));
}
RtpTransceiverInit CreateTransceiverInit(
const std::vector<cricket::SimulcastLayer>& layers) {
RtpTransceiverInit init;
for (const cricket::SimulcastLayer& layer : layers) {
RtpEncodingParameters encoding;
encoding.rid = layer.rid;
encoding.active = !layer.is_paused;
init.send_encodings.push_back(encoding);
}
return init;
}
cricket::SimulcastDescription RemoveSimulcast(SessionDescriptionInterface* sd) {
auto mcd = sd->description()->contents()[0].media_description();
auto result = mcd->simulcast_description();
mcd->set_simulcast_description(cricket::SimulcastDescription());
return result;
}
} // namespace webrtc

View file

@ -0,0 +1,39 @@
/*
* Copyright 2023 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 PC_TEST_SIMULCAST_LAYER_UTIL_H_
#define PC_TEST_SIMULCAST_LAYER_UTIL_H_
#include <string>
#include <vector>
#include "api/jsep.h"
#include "api/rtp_transceiver_interface.h"
#include "pc/session_description.h"
#include "pc/simulcast_description.h"
namespace webrtc {
std::vector<cricket::SimulcastLayer> CreateLayers(
const std::vector<std::string>& rids,
const std::vector<bool>& active);
std::vector<cricket::SimulcastLayer> CreateLayers(
const std::vector<std::string>& rids,
bool active);
RtpTransceiverInit CreateTransceiverInit(
const std::vector<cricket::SimulcastLayer>& layers);
cricket::SimulcastDescription RemoveSimulcast(SessionDescriptionInterface* sd);
} // namespace webrtc
#endif // PC_TEST_SIMULCAST_LAYER_UTIL_H_

View file

@ -0,0 +1,45 @@
/*
* Copyright 2017 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 PC_TEST_SRTP_TEST_UTIL_H_
#define PC_TEST_SRTP_TEST_UTIL_H_
#include <string>
namespace rtc {
extern const char kCsAesCm128HmacSha1_32[];
extern const char kCsAeadAes128Gcm[];
extern const char kCsAeadAes256Gcm[];
static const uint8_t kTestKey1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234";
static const uint8_t kTestKey2[] = "4321ZYXWVUTSRQPONMLKJIHGFEDCBA";
static const int kTestKeyLen = 30;
static int rtp_auth_tag_len(const std::string& cs) {
if (cs == kCsAesCm128HmacSha1_32) {
return 4;
} else if (cs == kCsAeadAes128Gcm || cs == kCsAeadAes256Gcm) {
return 16;
} else {
return 10;
}
}
static int rtcp_auth_tag_len(const std::string& cs) {
if (cs == kCsAeadAes128Gcm || cs == kCsAeadAes256Gcm) {
return 16;
} else {
return 10;
}
}
} // namespace rtc
#endif // PC_TEST_SRTP_TEST_UTIL_H_

View file

@ -0,0 +1,507 @@
/*
* Copyright (c) 2022 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 <memory>
#include <string>
#include <utility>
#include <vector>
#include "api/media_stream_interface.h"
#include "api/stats/rtcstats_objects.h"
#include "api/test/create_network_emulation_manager.h"
#include "api/test/create_peer_connection_quality_test_frame_generator.h"
#include "api/test/create_peerconnection_quality_test_fixture.h"
#include "api/test/frame_generator_interface.h"
#include "api/test/metrics/global_metrics_logger_and_exporter.h"
#include "api/test/network_emulation_manager.h"
#include "api/test/pclf/media_configuration.h"
#include "api/test/pclf/media_quality_test_params.h"
#include "api/test/pclf/peer_configurer.h"
#include "api/test/peerconnection_quality_test_fixture.h"
#include "api/test/simulated_network.h"
#include "api/test/time_controller.h"
#include "api/video_codecs/vp9_profile.h"
#include "call/simulated_network.h"
#include "modules/video_coding/codecs/vp9/include/vp9.h"
#include "modules/video_coding/svc/scalability_mode_util.h"
#include "rtc_base/containers/flat_map.h"
#include "system_wrappers/include/field_trial.h"
#include "test/field_trial.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/pc/e2e/analyzer/video/default_video_quality_analyzer.h"
#include "test/pc/e2e/network_quality_metrics_reporter.h"
#include "test/testsupport/file_utils.h"
namespace webrtc {
namespace {
using ::cricket::kAv1CodecName;
using ::cricket::kH264CodecName;
using ::cricket::kVp8CodecName;
using ::cricket::kVp9CodecName;
using ::testing::Combine;
using ::testing::Optional;
using ::testing::UnitTest;
using ::testing::Values;
using ::testing::ValuesIn;
using ::webrtc::webrtc_pc_e2e::EmulatedSFUConfig;
using ::webrtc::webrtc_pc_e2e::PeerConfigurer;
using ::webrtc::webrtc_pc_e2e::RunParams;
using ::webrtc::webrtc_pc_e2e::ScreenShareConfig;
using ::webrtc::webrtc_pc_e2e::VideoCodecConfig;
using ::webrtc::webrtc_pc_e2e::VideoConfig;
std::unique_ptr<webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture>
CreateTestFixture(absl::string_view test_case_name,
TimeController& time_controller,
std::pair<EmulatedNetworkManagerInterface*,
EmulatedNetworkManagerInterface*> network_links,
rtc::FunctionView<void(PeerConfigurer*)> alice_configurer,
rtc::FunctionView<void(PeerConfigurer*)> bob_configurer,
std::unique_ptr<VideoQualityAnalyzerInterface>
video_quality_analyzer = nullptr) {
auto fixture = webrtc_pc_e2e::CreatePeerConnectionE2EQualityTestFixture(
std::string(test_case_name), time_controller, nullptr,
std::move(video_quality_analyzer));
auto alice = std::make_unique<PeerConfigurer>(
network_links.first->network_dependencies());
auto bob = std::make_unique<PeerConfigurer>(
network_links.second->network_dependencies());
alice_configurer(alice.get());
bob_configurer(bob.get());
fixture->AddPeer(std::move(alice));
fixture->AddPeer(std::move(bob));
return fixture;
}
// Takes the current active field trials set, and appends some new trials.
std::string AppendFieldTrials(std::string new_trial_string) {
return std::string(field_trial::GetFieldTrialString()) + new_trial_string;
}
enum class UseDependencyDescriptor {
Enabled,
Disabled,
};
struct SvcTestParameters {
static SvcTestParameters Create(const std::string& codec_name,
const std::string& scalability_mode_str) {
absl::optional<ScalabilityMode> scalability_mode =
ScalabilityModeFromString(scalability_mode_str);
RTC_CHECK(scalability_mode.has_value())
<< "Unsupported scalability mode: " << scalability_mode_str;
int num_spatial_layers =
ScalabilityModeToNumSpatialLayers(*scalability_mode);
int num_temporal_layers =
ScalabilityModeToNumTemporalLayers(*scalability_mode);
return SvcTestParameters{codec_name, scalability_mode_str,
num_spatial_layers, num_temporal_layers};
}
std::string codec_name;
std::string scalability_mode;
int expected_spatial_layers;
int expected_temporal_layers;
};
class SvcTest : public testing::TestWithParam<
std::tuple<SvcTestParameters, UseDependencyDescriptor>> {
public:
SvcTest()
: video_codec_config(ToVideoCodecConfig(SvcTestParameters().codec_name)) {
}
static VideoCodecConfig ToVideoCodecConfig(absl::string_view codec) {
if (codec == cricket::kVp9CodecName) {
return VideoCodecConfig(
cricket::kVp9CodecName,
{{kVP9FmtpProfileId, VP9ProfileToString(VP9Profile::kProfile0)}});
}
return VideoCodecConfig(codec);
}
const SvcTestParameters& SvcTestParameters() const {
return std::get<0>(GetParam());
}
bool UseDependencyDescriptor() const {
return std::get<1>(GetParam()) == UseDependencyDescriptor::Enabled;
}
bool IsSMode() const {
return SvcTestParameters().scalability_mode[0] == 'S';
}
protected:
VideoCodecConfig video_codec_config;
};
std::string SvcTestNameGenerator(
const testing::TestParamInfo<SvcTest::ParamType>& info) {
return std::get<0>(info.param).scalability_mode +
(std::get<1>(info.param) == UseDependencyDescriptor::Enabled ? "_DD"
: "");
}
} // namespace
// Records how many frames are seen for each spatial and temporal index at the
// encoder and decoder level.
class SvcVideoQualityAnalyzer : public DefaultVideoQualityAnalyzer {
public:
using SpatialTemporalLayerCounts = flat_map<int, flat_map<int, int>>;
explicit SvcVideoQualityAnalyzer(Clock* clock)
: DefaultVideoQualityAnalyzer(clock,
test::GetGlobalMetricsLogger(),
DefaultVideoQualityAnalyzerOptions{
.compute_psnr = false,
.compute_ssim = false,
}) {}
~SvcVideoQualityAnalyzer() override = default;
void OnFrameEncoded(absl::string_view peer_name,
uint16_t frame_id,
const EncodedImage& encoded_image,
const EncoderStats& stats,
bool discarded) override {
absl::optional<int> spatial_id = encoded_image.SpatialIndex();
absl::optional<int> temporal_id = encoded_image.TemporalIndex();
encoder_layers_seen_[spatial_id.value_or(0)][temporal_id.value_or(0)]++;
DefaultVideoQualityAnalyzer::OnFrameEncoded(
peer_name, frame_id, encoded_image, stats, discarded);
}
void OnFramePreDecode(absl::string_view peer_name,
uint16_t frame_id,
const EncodedImage& input_image) override {
absl::optional<int> spatial_id = input_image.SpatialIndex();
absl::optional<int> temporal_id = input_image.TemporalIndex();
if (!spatial_id) {
decoder_layers_seen_[0][temporal_id.value_or(0)]++;
} else {
for (int i = 0; i <= *spatial_id; ++i) {
// If there are no spatial layers (for example VP8), we still want to
// record the temporal index for pseudo-layer "0" frames.
if (*spatial_id == 0 ||
input_image.SpatialLayerFrameSize(i).value_or(0) > 0) {
decoder_layers_seen_[i][temporal_id.value_or(0)]++;
}
}
}
DefaultVideoQualityAnalyzer::OnFramePreDecode(peer_name, frame_id,
input_image);
}
void OnStatsReports(
absl::string_view pc_label,
const rtc::scoped_refptr<const RTCStatsReport>& report) override {
// Extract the scalability mode reported in the stats.
auto outbound_stats = report->GetStatsOfType<RTCOutboundRtpStreamStats>();
for (const auto& stat : outbound_stats) {
if (stat->scalability_mode.has_value()) {
reported_scalability_mode_ = *stat->scalability_mode;
}
}
}
const SpatialTemporalLayerCounts& encoder_layers_seen() const {
return encoder_layers_seen_;
}
const SpatialTemporalLayerCounts& decoder_layers_seen() const {
return decoder_layers_seen_;
}
const absl::optional<std::string> reported_scalability_mode() const {
return reported_scalability_mode_;
}
private:
SpatialTemporalLayerCounts encoder_layers_seen_;
SpatialTemporalLayerCounts decoder_layers_seen_;
absl::optional<std::string> reported_scalability_mode_;
};
MATCHER_P2(HasSpatialAndTemporalLayers,
expected_spatial_layers,
expected_temporal_layers,
"") {
if (arg.size() != static_cast<size_t>(expected_spatial_layers)) {
*result_listener << "spatial layer count mismatch expected "
<< expected_spatial_layers << " but got " << arg.size();
return false;
}
for (const auto& [spatial_layer_index, temporal_layers] : arg) {
if (spatial_layer_index < 0 ||
spatial_layer_index >= expected_spatial_layers) {
*result_listener << "spatial layer index is not in range [0,"
<< expected_spatial_layers << "[.";
return false;
}
if (temporal_layers.size() !=
static_cast<size_t>(expected_temporal_layers)) {
*result_listener << "temporal layer count mismatch on spatial layer "
<< spatial_layer_index << ", expected "
<< expected_temporal_layers << " but got "
<< temporal_layers.size();
return false;
}
for (const auto& [temporal_layer_index, temporal_layer_frame_count] :
temporal_layers) {
if (temporal_layer_index < 0 ||
temporal_layer_index >= expected_temporal_layers) {
*result_listener << "temporal layer index on spatial layer "
<< spatial_layer_index << " is not in range [0,"
<< expected_temporal_layers << "[.";
return false;
}
}
}
return true;
}
MATCHER_P2(HasSpatialAndTemporalLayersSMode,
expected_spatial_layers,
expected_temporal_layers,
"") {
if (arg.size() != 1) {
*result_listener << "spatial layer count mismatch expected 1 but got "
<< arg.size();
return false;
}
for (const auto& [spatial_layer_index, temporal_layers] : arg) {
if (spatial_layer_index != expected_spatial_layers - 1) {
*result_listener << "spatial layer index is not equal to "
<< expected_spatial_layers - 1 << ".";
return false;
}
if (temporal_layers.size() !=
static_cast<size_t>(expected_temporal_layers)) {
*result_listener << "temporal layer count mismatch on spatial layer "
<< spatial_layer_index << ", expected "
<< expected_temporal_layers << " but got "
<< temporal_layers.size();
return false;
}
for (const auto& [temporal_layer_index, temporal_layer_frame_count] :
temporal_layers) {
if (temporal_layer_index < 0 ||
temporal_layer_index >= expected_temporal_layers) {
*result_listener << "temporal layer index on spatial layer "
<< spatial_layer_index << " is not in range [0,"
<< expected_temporal_layers << "[.";
return false;
}
}
}
return true;
}
TEST_P(SvcTest, ScalabilityModeSupported) {
std::string trials;
if (UseDependencyDescriptor()) {
trials += "WebRTC-DependencyDescriptorAdvertised/Enabled/";
}
test::ScopedFieldTrials override_trials(AppendFieldTrials(trials));
std::unique_ptr<NetworkEmulationManager> network_emulation_manager =
CreateNetworkEmulationManager(TimeMode::kSimulated);
auto analyzer = std::make_unique<SvcVideoQualityAnalyzer>(
network_emulation_manager->time_controller()->GetClock());
SvcVideoQualityAnalyzer* analyzer_ptr = analyzer.get();
auto fixture = CreateTestFixture(
UnitTest::GetInstance()->current_test_info()->name(),
*network_emulation_manager->time_controller(),
network_emulation_manager->CreateEndpointPairWithTwoWayRoutes(
BuiltInNetworkBehaviorConfig()),
[this](PeerConfigurer* alice) {
VideoConfig video(/*stream_label=*/"alice-video", /*width=*/1850,
/*height=*/1110, /*fps=*/30);
if (IsSMode()) {
video.emulated_sfu_config = EmulatedSFUConfig(
SvcTestParameters().expected_spatial_layers - 1,
SvcTestParameters().expected_temporal_layers - 1);
}
RtpEncodingParameters parameters;
parameters.scalability_mode = SvcTestParameters().scalability_mode;
video.encoding_params.push_back(parameters);
auto generator = CreateScreenShareFrameGenerator(
video, ScreenShareConfig(TimeDelta::Seconds(5)));
alice->AddVideoConfig(std::move(video), std::move(generator));
alice->SetVideoCodecs({video_codec_config});
},
[](PeerConfigurer* bob) {}, std::move(analyzer));
fixture->Run(RunParams(TimeDelta::Seconds(10)));
EXPECT_THAT(analyzer_ptr->encoder_layers_seen(),
HasSpatialAndTemporalLayers(
SvcTestParameters().expected_spatial_layers,
SvcTestParameters().expected_temporal_layers));
if (IsSMode()) {
EXPECT_THAT(analyzer_ptr->decoder_layers_seen(),
HasSpatialAndTemporalLayersSMode(
SvcTestParameters().expected_spatial_layers,
SvcTestParameters().expected_temporal_layers));
} else {
EXPECT_THAT(analyzer_ptr->decoder_layers_seen(),
HasSpatialAndTemporalLayers(
SvcTestParameters().expected_spatial_layers,
SvcTestParameters().expected_temporal_layers));
}
EXPECT_THAT(analyzer_ptr->reported_scalability_mode(),
Optional(SvcTestParameters().scalability_mode));
RTC_LOG(LS_INFO) << "Encoder layers seen: "
<< analyzer_ptr->encoder_layers_seen().size();
for (auto& [spatial_index, temporal_layers] :
analyzer_ptr->encoder_layers_seen()) {
for (auto& [temporal_index, frame_count] : temporal_layers) {
RTC_LOG(LS_INFO) << " Layer: " << spatial_index << "," << temporal_index
<< " frames: " << frame_count;
}
}
RTC_LOG(LS_INFO) << "Decoder layers seen: "
<< analyzer_ptr->decoder_layers_seen().size();
for (auto& [spatial_index, temporal_layers] :
analyzer_ptr->decoder_layers_seen()) {
for (auto& [temporal_index, frame_count] : temporal_layers) {
RTC_LOG(LS_INFO) << " Layer: " << spatial_index << "," << temporal_index
<< " frames: " << frame_count;
}
}
}
INSTANTIATE_TEST_SUITE_P(
SvcTestVP8,
SvcTest,
Combine(Values(SvcTestParameters::Create(kVp8CodecName, "L1T1"),
SvcTestParameters::Create(kVp8CodecName, "L1T2"),
SvcTestParameters::Create(kVp8CodecName, "L1T3")),
Values(UseDependencyDescriptor::Disabled,
UseDependencyDescriptor::Enabled)),
SvcTestNameGenerator);
#if defined(WEBRTC_USE_H264)
INSTANTIATE_TEST_SUITE_P(
SvcTestH264,
SvcTest,
Combine(ValuesIn({
SvcTestParameters::Create(kH264CodecName, "L1T1"),
SvcTestParameters::Create(kH264CodecName, "L1T2"),
SvcTestParameters::Create(kH264CodecName, "L1T3"),
}),
// Like AV1, H.264 RTP format does not include SVC related
// information, so always use Dependency Descriptor.
Values(UseDependencyDescriptor::Enabled)),
SvcTestNameGenerator);
#endif
#if defined(RTC_ENABLE_VP9)
INSTANTIATE_TEST_SUITE_P(
SvcTestVP9,
SvcTest,
Combine(
// TODO(bugs.webrtc.org/13960): Fix and enable remaining VP9 modes
ValuesIn({
SvcTestParameters::Create(kVp9CodecName, "L1T1"),
SvcTestParameters::Create(kVp9CodecName, "L1T2"),
SvcTestParameters::Create(kVp9CodecName, "L1T3"),
SvcTestParameters::Create(kVp9CodecName, "L2T1"),
SvcTestParameters::Create(kVp9CodecName, "L2T1h"),
SvcTestParameters::Create(kVp9CodecName, "L2T1_KEY"),
SvcTestParameters::Create(kVp9CodecName, "L2T2"),
SvcTestParameters::Create(kVp9CodecName, "L2T2h"),
SvcTestParameters::Create(kVp9CodecName, "L2T2_KEY"),
SvcTestParameters::Create(kVp9CodecName, "L2T2_KEY_SHIFT"),
SvcTestParameters::Create(kVp9CodecName, "L2T3"),
SvcTestParameters::Create(kVp9CodecName, "L2T3h"),
SvcTestParameters::Create(kVp9CodecName, "L2T3_KEY"),
// SvcTestParameters::Create(kVp9CodecName, "L2T3_KEY_SHIFT"),
SvcTestParameters::Create(kVp9CodecName, "L3T1"),
SvcTestParameters::Create(kVp9CodecName, "L3T1h"),
SvcTestParameters::Create(kVp9CodecName, "L3T1_KEY"),
SvcTestParameters::Create(kVp9CodecName, "L3T2"),
SvcTestParameters::Create(kVp9CodecName, "L3T2h"),
SvcTestParameters::Create(kVp9CodecName, "L3T2_KEY"),
// SvcTestParameters::Create(kVp9CodecName, "L3T2_KEY_SHIFT"),
SvcTestParameters::Create(kVp9CodecName, "L3T3"),
SvcTestParameters::Create(kVp9CodecName, "L3T3h"),
SvcTestParameters::Create(kVp9CodecName, "L3T3_KEY"),
// SvcTestParameters::Create(kVp9CodecName, "L3T3_KEY_SHIFT"),
SvcTestParameters::Create(kVp9CodecName, "S2T1"),
SvcTestParameters::Create(kVp9CodecName, "S2T1h"),
SvcTestParameters::Create(kVp9CodecName, "S2T2"),
SvcTestParameters::Create(kVp9CodecName, "S2T2h"),
SvcTestParameters::Create(kVp9CodecName, "S2T3"),
SvcTestParameters::Create(kVp9CodecName, "S2T3h"),
SvcTestParameters::Create(kVp9CodecName, "S3T1"),
SvcTestParameters::Create(kVp9CodecName, "S3T1h"),
SvcTestParameters::Create(kVp9CodecName, "S3T2"),
SvcTestParameters::Create(kVp9CodecName, "S3T2h"),
SvcTestParameters::Create(kVp9CodecName, "S3T3"),
SvcTestParameters::Create(kVp9CodecName, "S3T3h"),
}),
Values(UseDependencyDescriptor::Disabled,
UseDependencyDescriptor::Enabled)),
SvcTestNameGenerator);
#endif
INSTANTIATE_TEST_SUITE_P(
SvcTestAV1,
SvcTest,
Combine(ValuesIn({
SvcTestParameters::Create(kAv1CodecName, "L1T1"),
SvcTestParameters::Create(kAv1CodecName, "L1T2"),
SvcTestParameters::Create(kAv1CodecName, "L1T3"),
SvcTestParameters::Create(kAv1CodecName, "L2T1"),
SvcTestParameters::Create(kAv1CodecName, "L2T1h"),
SvcTestParameters::Create(kAv1CodecName, "L2T1_KEY"),
SvcTestParameters::Create(kAv1CodecName, "L2T2"),
SvcTestParameters::Create(kAv1CodecName, "L2T2h"),
SvcTestParameters::Create(kAv1CodecName, "L2T2_KEY"),
SvcTestParameters::Create(kAv1CodecName, "L2T2_KEY_SHIFT"),
SvcTestParameters::Create(kAv1CodecName, "L2T3"),
SvcTestParameters::Create(kAv1CodecName, "L2T3h"),
SvcTestParameters::Create(kAv1CodecName, "L2T3_KEY"),
// SvcTestParameters::Create(kAv1CodecName, "L2T3_KEY_SHIFT"),
// TODO(bugs.webrtc.org/15666): Investigate and reenable AV1
// L3 tests. SvcTestParameters::Create(kAv1CodecName, "L3T1"),
// SvcTestParameters::Create(kAv1CodecName, "L3T1h"),
// SvcTestParameters::Create(kAv1CodecName, "L3T1_KEY"),
// SvcTestParameters::Create(kAv1CodecName, "L3T2"),
// SvcTestParameters::Create(kAv1CodecName, "L3T2h"),
// SvcTestParameters::Create(kAv1CodecName, "L3T2_KEY"),
// SvcTestParameters::Create(kAv1CodecName, "L3T2_KEY_SHIFT"),
// SvcTestParameters::Create(kAv1CodecName, "L3T3"),
// SvcTestParameters::Create(kAv1CodecName, "L3T3h"),
// SvcTestParameters::Create(kAv1CodecName, "L3T3_KEY"),
// SvcTestParameters::Create(kAv1CodecName, "L3T3_KEY_SHIFT"),
SvcTestParameters::Create(kAv1CodecName, "S2T1"),
SvcTestParameters::Create(kAv1CodecName, "S2T1h"),
SvcTestParameters::Create(kAv1CodecName, "S2T2"),
SvcTestParameters::Create(kAv1CodecName, "S2T2h"),
SvcTestParameters::Create(kAv1CodecName, "S2T3"),
SvcTestParameters::Create(kAv1CodecName, "S2T3h"),
// TODO(bugs.webrtc.org/15666): Investigate and reenable AV1
// S3 tests.
// SvcTestParameters::Create(kAv1CodecName, "S3T1"),
// SvcTestParameters::Create(kAv1CodecName, "S3T1h"),
// SvcTestParameters::Create(kAv1CodecName, "S3T2"),
// SvcTestParameters::Create(kAv1CodecName, "S3T2h"),
// SvcTestParameters::Create(kAv1CodecName, "S3T3"),
// SvcTestParameters::Create(kAv1CodecName, "S3T3h"),
}),
Values(UseDependencyDescriptor::Enabled)),
SvcTestNameGenerator);
} // namespace webrtc

View file

@ -0,0 +1,184 @@
/*
* Copyright 2012 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.
*/
// This file contain SDP strings used for testing.
#ifndef PC_TEST_TEST_SDP_STRINGS_H_
#define PC_TEST_TEST_SDP_STRINGS_H_
namespace webrtc {
// SDP offer string from a Nightly FireFox build.
static const char kFireFoxSdpOffer[] =
"v=0\r\n"
"o=Mozilla-SIPUA 23551 0 IN IP4 0.0.0.0\r\n"
"s=SIP Call\r\n"
"t=0 0\r\n"
"a=ice-ufrag:e5785931\r\n"
"a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
"a=fingerprint:sha-256 A7:24:72:CA:6E:02:55:39:BA:66:DF:6E:CC:4C:D8:B0:1A:"
"BF:1A:56:65:7D:F4:03:AD:7E:77:43:2A:29:EC:93\r\n"
"m=audio 36993 RTP/SAVPF 109 0 8 101\r\n"
"c=IN IP4 74.95.2.170\r\n"
"a=rtpmap:109 opus/48000/2\r\n"
"a=ptime:20\r\n"
"a=rtcp-mux\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:101 telephone-event/8000\r\n"
"a=fmtp:101 0-15\r\n"
"a=sendrecv\r\n"
"a=candidate:0 1 UDP 2112946431 172.16.191.1 61725 typ host\r\n"
"a=candidate:2 1 UDP 2112487679 172.16.131.1 58798 typ host\r\n"
"a=candidate:4 1 UDP 2113667327 10.0.254.2 58122 typ host\r\n"
"a=candidate:5 1 UDP 1694302207 74.95.2.170 36993 typ srflx raddr "
"10.0.254.2 rport 58122\r\n"
"a=candidate:0 2 UDP 2112946430 172.16.191.1 55025 typ host\r\n"
"a=candidate:2 2 UDP 2112487678 172.16.131.1 63576 typ host\r\n"
"a=candidate:4 2 UDP 2113667326 10.0.254.2 50962 typ host\r\n"
"a=candidate:5 2 UDP 1694302206 74.95.2.170 41028 typ srflx raddr"
" 10.0.254.2 rport 50962\r\n"
"m=video 38826 RTP/SAVPF 120\r\n"
"c=IN IP4 74.95.2.170\r\n"
"a=rtcp-mux\r\n"
"a=rtpmap:120 VP8/90000\r\n"
"a=sendrecv\r\n"
"a=candidate:0 1 UDP 2112946431 172.16.191.1 62017 typ host\r\n"
"a=candidate:2 1 UDP 2112487679 172.16.131.1 59741 typ host\r\n"
"a=candidate:4 1 UDP 2113667327 10.0.254.2 62652 typ host\r\n"
"a=candidate:5 1 UDP 1694302207 74.95.2.170 38826 typ srflx raddr"
" 10.0.254.2 rport 62652\r\n"
"a=candidate:0 2 UDP 2112946430 172.16.191.1 63440 typ host\r\n"
"a=candidate:2 2 UDP 2112487678 172.16.131.1 51847 typ host\r\n"
"a=candidate:4 2 UDP 2113667326 10.0.254.2 58890 typ host\r\n"
"a=candidate:5 2 UDP 1694302206 74.95.2.170 33611 typ srflx raddr"
" 10.0.254.2 rport 58890\r\n"
#ifdef WEBRTC_HAVE_SCTP
"m=application 45536 DTLS/SCTP 5000\r\n"
"c=IN IP4 74.95.2.170\r\n"
"a=fmtp:5000 protocol=webrtc-datachannel;streams=16\r\n"
"a=sendrecv\r\n"
"a=candidate:0 1 UDP 2112946431 172.16.191.1 60248 typ host\r\n"
"a=candidate:2 1 UDP 2112487679 172.16.131.1 55925 typ host\r\n"
"a=candidate:4 1 UDP 2113667327 10.0.254.2 65268 typ host\r\n"
"a=candidate:5 1 UDP 1694302207 74.95.2.170 45536 typ srflx raddr"
" 10.0.254.2 rport 65268\r\n"
"a=candidate:0 2 UDP 2112946430 172.16.191.1 49162 typ host\r\n"
"a=candidate:2 2 UDP 2112487678 172.16.131.1 59635 typ host\r\n"
"a=candidate:4 2 UDP 2113667326 10.0.254.2 61232 typ host\r\n"
"a=candidate:5 2 UDP 1694302206 74.95.2.170 45468 typ srflx raddr"
" 10.0.254.2 rport 61232\r\n"
#endif
; // NOLINT(whitespace/semicolon)
// Audio SDP with a limited set of audio codecs.
static const char kAudioSdpPlanB[] =
"v=0\r\n"
"o=- 7859371131 2 IN IP4 192.168.30.208\r\n"
"s=-\r\n"
"c=IN IP4 192.168.30.208\r\n"
"t=0 0\r\n"
"m=audio 16000 RTP/SAVPF 0 8 126\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:126 telephone-event/8000\r\n"
"a=sendrecv\r\n"
"a=rtcp:16000 IN IP4 192.168.30.208\r\n"
"a=rtcp-mux\r\n"
"a=crypto:0 AES_CM_128_HMAC_SHA1_80 "
"inline:tvKIFjbMQ7W0/C2RzhwN0oQglj/7GJg+frdsNRxt\r\n"
"a=ice-ufrag:AI2sRT3r\r\n"
"a=ice-pwd:lByS9z2RSQlSE9XurlvjYmEm\r\n"
"a=ssrc:4227871655 cname:GeAAgb6XCPNLVMX5\r\n"
"a=ssrc:4227871655 msid:1NFAV3iD08ioO2339rQS9pfOI9mDf6GeG9F4 a0\r\n"
"a=ssrc:4227871655 mslabel:1NFAV3iD08ioO2339rQS9pfOI9mDf6GeG9F4\r\n"
"a=ssrc:4227871655 label:1NFAV3iD08ioO2339rQS9pfOI9mDf6GeG9F4a0\r\n"
"a=mid:audio\r\n";
// Same string as above but with the MID changed to the Unified Plan default.
// This is needed so that this SDP can be used as an answer for a Unified Plan
// offer.
static const char kAudioSdpUnifiedPlan[] =
"v=0\r\n"
"o=- 7859371131 2 IN IP4 192.168.30.208\r\n"
"s=-\r\n"
"c=IN IP4 192.168.30.208\r\n"
"t=0 0\r\n"
"m=audio 16000 RTP/SAVPF 0 8 126\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:126 telephone-event/8000\r\n"
"a=sendrecv\r\n"
"a=rtcp:16000 IN IP4 192.168.30.208\r\n"
"a=rtcp-mux\r\n"
"a=crypto:0 AES_CM_128_HMAC_SHA1_80 "
"inline:tvKIFjbMQ7W0/C2RzhwN0oQglj/7GJg+frdsNRxt\r\n"
"a=ice-ufrag:AI2sRT3r\r\n"
"a=ice-pwd:lByS9z2RSQlSE9XurlvjYmEm\r\n"
"a=ssrc:4227871655 cname:GeAAgb6XCPNLVMX5\r\n"
"a=ssrc:4227871655 msid:1NFAV3iD08ioO2339rQS9pfOI9mDf6GeG9F4 a0\r\n"
"a=ssrc:4227871655 mslabel:1NFAV3iD08ioO2339rQS9pfOI9mDf6GeG9F4\r\n"
"a=ssrc:4227871655 label:1NFAV3iD08ioO2339rQS9pfOI9mDf6GeG9F4a0\r\n"
"a=mid:0\r\n";
static const char kAudioSdpWithUnsupportedCodecsPlanB[] =
"v=0\r\n"
"o=- 6858750541 2 IN IP4 192.168.30.208\r\n"
"s=-\r\n"
"c=IN IP4 192.168.30.208\r\n"
"t=0 0\r\n"
"m=audio 16000 RTP/SAVPF 0 8 109 110 126\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:109 WeirdCodec1/8000\r\n"
"a=rtpmap:110 WeirdCodec2/8000\r\n"
"a=rtpmap:126 telephone-event/8000\r\n"
"a=sendonly\r\n"
"a=rtcp:16000 IN IP4 192.168.30.208\r\n"
"a=rtcp-mux\r\n"
"a=crypto:0 AES_CM_128_HMAC_SHA1_80 "
"inline:tvKIFjbMQ7W0/C2RzhwN0oQglj/7GJg+frdsNRxt\r\n"
"a=ice-ufrag:AI2sRT3r\r\n"
"a=ice-pwd:lByS9z2RSQlSE9XurlvjYmEm\r\n"
"a=ssrc:4227871655 cname:TsmD02HRfhkJBm4m\r\n"
"a=ssrc:4227871655 msid:7nU0TApbB-n4dfPlCplWT9QTEsbBDS1IlpW3 a0\r\n"
"a=ssrc:4227871655 mslabel:7nU0TApbB-n4dfPlCplWT9QTEsbBDS1IlpW3\r\n"
"a=ssrc:4227871655 label:7nU0TApbB-n4dfPlCplWT9QTEsbBDS1IlpW3a0\r\n"
"a=mid:audio\r\n";
// Same string as above but with the MID changed to the Unified Plan default.
// This is needed so that this SDP can be used as an answer for a Unified Plan
// offer.
static const char kAudioSdpWithUnsupportedCodecsUnifiedPlan[] =
"v=0\r\n"
"o=- 6858750541 2 IN IP4 192.168.30.208\r\n"
"s=-\r\n"
"c=IN IP4 192.168.30.208\r\n"
"t=0 0\r\n"
"m=audio 16000 RTP/SAVPF 0 8 109 110 126\r\n"
"a=rtpmap:0 PCMU/8000\r\n"
"a=rtpmap:8 PCMA/8000\r\n"
"a=rtpmap:109 WeirdCodec1/8000\r\n"
"a=rtpmap:110 WeirdCodec2/8000\r\n"
"a=rtpmap:126 telephone-event/8000\r\n"
"a=sendonly\r\n"
"a=rtcp:16000 IN IP4 192.168.30.208\r\n"
"a=rtcp-mux\r\n"
"a=crypto:0 AES_CM_128_HMAC_SHA1_80 "
"inline:tvKIFjbMQ7W0/C2RzhwN0oQglj/7GJg+frdsNRxt\r\n"
"a=ice-ufrag:AI2sRT3r\r\n"
"a=ice-pwd:lByS9z2RSQlSE9XurlvjYmEm\r\n"
"a=ssrc:4227871655 cname:TsmD02HRfhkJBm4m\r\n"
"a=ssrc:4227871655 msid:7nU0TApbB-n4dfPlCplWT9QTEsbBDS1IlpW3 a0\r\n"
"a=ssrc:4227871655 mslabel:7nU0TApbB-n4dfPlCplWT9QTEsbBDS1IlpW3\r\n"
"a=ssrc:4227871655 label:7nU0TApbB-n4dfPlCplWT9QTEsbBDS1IlpW3a0\r\n"
"a=mid:0\r\n";
} // namespace webrtc
#endif // PC_TEST_TEST_SDP_STRINGS_H_