blob: ab6aac9cf8a6d13621b5db3115f5cfd5b09c4a01 [file] [log] [blame]
/*
* Copyright (c) 2019 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 TEST_PEER_SCENARIO_PEER_SCENARIO_CLIENT_H_
#define TEST_PEER_SCENARIO_PEER_SCENARIO_CLIENT_H_
#include <functional>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "absl/memory/memory.h"
#include "api/peer_connection_interface.h"
#include "api/test/network_emulation_manager.h"
#include "api/test/time_controller.h"
#include "pc/test/frame_generator_capturer_video_track_source.h"
#include "test/logging/log_writer.h"
namespace webrtc {
namespace test {
// Wrapper for a PeerConnection for use in PeerScenario tests. It's intended to
// be a minimal wrapper for a peer connection that's simple to use in testing.
// In particular the constructor hides a lot of the required setup for a peer
// connection.
class PeerScenarioClient {
public:
struct CallbackHandlers {
std::vector<std::function<void(PeerConnectionInterface::SignalingState)>>
on_signaling_change;
std::vector<std::function<void(rtc::scoped_refptr<DataChannelInterface>)>>
on_data_channel;
std::vector<std::function<void()>> on_renegotiation_needed;
std::vector<
std::function<void(PeerConnectionInterface::IceConnectionState)>>
on_standardized_ice_connection_change;
std::vector<
std::function<void(PeerConnectionInterface::PeerConnectionState)>>
on_connection_change;
std::vector<std::function<void(PeerConnectionInterface::IceGatheringState)>>
on_ice_gathering_change;
std::vector<std::function<void(const IceCandidateInterface*)>>
on_ice_candidate;
std::vector<std::function<void(const std::string&,
int,
const std::string&,
int,
const std::string&)>>
on_ice_candidate_error;
std::vector<std::function<void(const std::vector<cricket::Candidate>&)>>
on_ice_candidates_removed;
std::vector<std::function<void(
rtc::scoped_refptr<RtpReceiverInterface>,
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&)>>
on_add_track;
std::vector<
std::function<void(rtc::scoped_refptr<RtpTransceiverInterface>)>>
on_track;
std::vector<std::function<void(rtc::scoped_refptr<RtpReceiverInterface>)>>
on_remove_track;
};
struct Config {
// WebRTC only support one audio device that is setup up on construction, so
// we provide the audio generator configuration here rather than on creation
// of the tracks. This is unlike video, where multiple capture sources can
// be used at the same time.
struct AudioSource {
int sample_rate = 48000;
int channels = 1;
struct PulsedNoise {
double amplitude = 0.1;
};
absl::optional<PulsedNoise> pulsed_noise = PulsedNoise();
} audio;
struct Video {
bool use_fake_codecs = false;
} video;
// The created endpoints can be accessed using the map key as `index` in
// PeerScenarioClient::endpoint(index).
std::map<int, EmulatedEndpointConfig> endpoints = {
{0, EmulatedEndpointConfig()}};
CallbackHandlers handlers;
PeerConnectionInterface::RTCConfiguration rtc_config;
bool disable_encryption = false;
Config() { rtc_config.sdp_semantics = SdpSemantics::kUnifiedPlan; }
};
struct VideoSendTrackConfig {
FrameGeneratorCapturerConfig generator;
bool screencast = false;
};
struct AudioSendTrack {
rtc::scoped_refptr<AudioTrackInterface> track;
rtc::scoped_refptr<RtpSenderInterface> sender;
};
struct VideoSendTrack {
// Raw pointer to the capturer owned by `source`.
FrameGeneratorCapturer* capturer;
rtc::scoped_refptr<FrameGeneratorCapturerVideoTrackSource> source;
rtc::scoped_refptr<VideoTrackInterface> track;
rtc::scoped_refptr<RtpSenderInterface> sender;
};
PeerScenarioClient(
NetworkEmulationManager* net,
rtc::Thread* signaling_thread,
std::unique_ptr<LogWriterFactoryInterface> log_writer_factory,
Config config);
PeerConnectionFactoryInterface* factory() { return pc_factory_.get(); }
PeerConnectionInterface* pc() {
RTC_DCHECK_RUN_ON(signaling_thread_);
return peer_connection_.get();
}
rtc::Thread* thread() { return signaling_thread_; }
Clock* clock() { return Clock::GetRealTimeClock(); }
// Returns the endpoint created from the EmulatedEndpointConfig with the same
// index in PeerScenarioClient::config.
EmulatedEndpoint* endpoint(int index = 0);
AudioSendTrack CreateAudio(std::string track_id,
cricket::AudioOptions options);
VideoSendTrack CreateVideo(std::string track_id, VideoSendTrackConfig config);
void AddVideoReceiveSink(std::string track_id,
rtc::VideoSinkInterface<VideoFrame>* video_sink);
CallbackHandlers* handlers() { return &handlers_; }
// The `munge_offer` function can be used to munge the SDP, i.e. modify a
// local description afer creating it but before setting it. Note that this is
// legacy behavior. It's added here only to be able to have test coverage for
// scenarios even if they are not spec compliant.
void CreateAndSetSdp(
std::function<void(SessionDescriptionInterface*)> munge_offer,
std::function<void(std::string)> offer_handler);
void SetSdpOfferAndGetAnswer(std::string remote_offer,
std::function<void(std::string)> answer_handler);
void SetSdpAnswer(
std::string remote_answer,
std::function<void(const SessionDescriptionInterface& answer)>
done_handler);
// Adds the given ice candidate when the peer connection is ready.
void AddIceCandidate(std::unique_ptr<IceCandidateInterface> candidate);
private:
const std::map<int, EmulatedEndpoint*> endpoints_;
TaskQueueFactory* const task_queue_factory_;
rtc::Thread* const signaling_thread_;
const std::unique_ptr<LogWriterFactoryInterface> log_writer_factory_;
const std::unique_ptr<rtc::Thread> worker_thread_;
CallbackHandlers handlers_ RTC_GUARDED_BY(signaling_thread_);
const std::unique_ptr<PeerConnectionObserver> observer_;
std::map<std::string, std::vector<rtc::VideoSinkInterface<VideoFrame>*>>
track_id_to_video_sinks_ RTC_GUARDED_BY(signaling_thread_);
std::list<std::unique_ptr<IceCandidateInterface>> pending_ice_candidates_
RTC_GUARDED_BY(signaling_thread_);
rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
rtc::scoped_refptr<PeerConnectionInterface> peer_connection_
RTC_GUARDED_BY(signaling_thread_);
};
} // namespace test
} // namespace webrtc
#endif // TEST_PEER_SCENARIO_PEER_SCENARIO_CLIENT_H_