Add AddTransceiver and GetTransceivers to PeerConnection
WebRTC 1.0 has added the transceiver API to PeerConnection. This is the first step towards exposing this to WebRTC consumers. For now, transceivers can be added and fetched but there is not yet support for creating offers/answers or setting local/remote descriptions. That support ("Unified Plan") will be added in follow-up CLs. The transceiver API is currently only available if the application opts in by specifying the kUnifiedPlan SDP semantics when creating the PeerConnection. Bug: webrtc:7600 Change-Id: I0b8ee24b489b45bb4c5f60b699bd20c61af01d8e Reviewed-on: https://webrtc-review.googlesource.com/23880 Commit-Queue: Steve Anton <steveanton@webrtc.org> Reviewed-by: Peter Thatcher <pthatcher@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20896}
This commit is contained in:
@ -82,6 +82,7 @@
|
|||||||
#include "api/rtceventlogoutput.h"
|
#include "api/rtceventlogoutput.h"
|
||||||
#include "api/rtpreceiverinterface.h"
|
#include "api/rtpreceiverinterface.h"
|
||||||
#include "api/rtpsenderinterface.h"
|
#include "api/rtpsenderinterface.h"
|
||||||
|
#include "api/rtptransceiverinterface.h"
|
||||||
#include "api/setremotedescriptionobserverinterface.h"
|
#include "api/setremotedescriptionobserverinterface.h"
|
||||||
#include "api/stats/rtcstatscollectorcallback.h"
|
#include "api/stats/rtcstatscollectorcallback.h"
|
||||||
#include "api/statstypes.h"
|
#include "api/statstypes.h"
|
||||||
@ -601,6 +602,57 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
|
|||||||
// Returns true on success.
|
// Returns true on success.
|
||||||
virtual bool RemoveTrack(RtpSenderInterface* sender) = 0;
|
virtual bool RemoveTrack(RtpSenderInterface* sender) = 0;
|
||||||
|
|
||||||
|
// AddTransceiver creates a new RtpTransceiver and adds it to the set of
|
||||||
|
// transceivers. Adding a transceiver will cause future calls to CreateOffer
|
||||||
|
// to add a media description for the corresponding transceiver.
|
||||||
|
//
|
||||||
|
// The initial value of |mid| in the returned transceiver is null. Setting a
|
||||||
|
// new session description may change it to a non-null value.
|
||||||
|
//
|
||||||
|
// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver
|
||||||
|
//
|
||||||
|
// Optionally, an RtpTransceiverInit structure can be specified to configure
|
||||||
|
// the transceiver from construction. If not specified, the transceiver will
|
||||||
|
// default to having a direction of kSendRecv and not be part of any streams.
|
||||||
|
//
|
||||||
|
// These methods are only available when Unified Plan is enabled (see
|
||||||
|
// RTCConfiguration).
|
||||||
|
//
|
||||||
|
// Common errors:
|
||||||
|
// - INTERNAL_ERROR: The configuration does not have Unified Plan enabled.
|
||||||
|
// TODO(steveanton): Make these pure virtual once downstream projects have
|
||||||
|
// updated.
|
||||||
|
|
||||||
|
// Adds a transceiver with a sender set to transmit the given track. The kind
|
||||||
|
// of the transceiver (and sender/receiver) will be derived from the kind of
|
||||||
|
// the track.
|
||||||
|
// Errors:
|
||||||
|
// - INVALID_PARAMETER: |track| is null.
|
||||||
|
virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR, "not implemented");
|
||||||
|
}
|
||||||
|
virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
|
const RtpTransceiverInit& init) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR, "not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a transceiver with the given kind. Can either be MEDIA_TYPE_AUDIO or
|
||||||
|
// MEDIA_TYPE_VIDEO.
|
||||||
|
// Errors:
|
||||||
|
// - INVALID_PARAMETER: |media_type| is not MEDIA_TYPE_AUDIO or
|
||||||
|
// MEDIA_TYPE_VIDEO.
|
||||||
|
virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
AddTransceiver(cricket::MediaType media_type) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR, "not implemented");
|
||||||
|
}
|
||||||
|
virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
AddTransceiver(cricket::MediaType media_type,
|
||||||
|
const RtpTransceiverInit& init) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR, "not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
// Returns pointer to a DtmfSender on success. Otherwise returns null.
|
// Returns pointer to a DtmfSender on success. Otherwise returns null.
|
||||||
//
|
//
|
||||||
// This API is no longer part of the standard; instead DtmfSenders are
|
// This API is no longer part of the standard; instead DtmfSenders are
|
||||||
@ -650,6 +702,15 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
|
|||||||
return std::vector<rtc::scoped_refptr<RtpReceiverInterface>>();
|
return std::vector<rtc::scoped_refptr<RtpReceiverInterface>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get all RtpTransceivers, created either through AddTransceiver, AddTrack or
|
||||||
|
// by a remote description applied with SetRemoteDescription.
|
||||||
|
// Note: This method is only available when Unified Plan is enabled (see
|
||||||
|
// RTCConfiguration).
|
||||||
|
virtual std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
GetTransceivers() const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool GetStats(StatsObserver* observer,
|
virtual bool GetStats(StatsObserver* observer,
|
||||||
MediaStreamTrackInterface* track,
|
MediaStreamTrackInterface* track,
|
||||||
StatsOutputLevel level) = 0;
|
StatsOutputLevel level) = 0;
|
||||||
|
@ -33,6 +33,20 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection)
|
|||||||
MediaStreamTrackInterface*,
|
MediaStreamTrackInterface*,
|
||||||
std::vector<MediaStreamInterface*>)
|
std::vector<MediaStreamInterface*>)
|
||||||
PROXY_METHOD1(bool, RemoveTrack, RtpSenderInterface*)
|
PROXY_METHOD1(bool, RemoveTrack, RtpSenderInterface*)
|
||||||
|
PROXY_METHOD1(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
|
||||||
|
AddTransceiver,
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface>)
|
||||||
|
PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
|
||||||
|
AddTransceiver,
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface>,
|
||||||
|
const RtpTransceiverInit&)
|
||||||
|
PROXY_METHOD1(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
|
||||||
|
AddTransceiver,
|
||||||
|
cricket::MediaType)
|
||||||
|
PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
|
||||||
|
AddTransceiver,
|
||||||
|
cricket::MediaType,
|
||||||
|
const RtpTransceiverInit&)
|
||||||
PROXY_METHOD1(rtc::scoped_refptr<DtmfSenderInterface>,
|
PROXY_METHOD1(rtc::scoped_refptr<DtmfSenderInterface>,
|
||||||
CreateDtmfSender,
|
CreateDtmfSender,
|
||||||
AudioTrackInterface*)
|
AudioTrackInterface*)
|
||||||
@ -44,6 +58,8 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection)
|
|||||||
GetSenders)
|
GetSenders)
|
||||||
PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpReceiverInterface>>,
|
PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpReceiverInterface>>,
|
||||||
GetReceivers)
|
GetReceivers)
|
||||||
|
PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>,
|
||||||
|
GetTransceivers)
|
||||||
PROXY_METHOD3(bool,
|
PROXY_METHOD3(bool,
|
||||||
GetStats,
|
GetStats,
|
||||||
StatsObserver*,
|
StatsObserver*,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#define API_RTPTRANSCEIVERINTERFACE_H_
|
#define API_RTPTRANSCEIVERINTERFACE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "api/optional.h"
|
#include "api/optional.h"
|
||||||
#include "api/rtpreceiverinterface.h"
|
#include "api/rtpreceiverinterface.h"
|
||||||
@ -20,6 +21,7 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection
|
||||||
enum class RtpTransceiverDirection {
|
enum class RtpTransceiverDirection {
|
||||||
kSendRecv,
|
kSendRecv,
|
||||||
kSendOnly,
|
kSendOnly,
|
||||||
@ -27,6 +29,21 @@ enum class RtpTransceiverDirection {
|
|||||||
kInactive
|
kInactive
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Structure for initializing an RtpTransceiver in a call to
|
||||||
|
// PeerConnectionInterface::AddTransceiver.
|
||||||
|
// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit
|
||||||
|
struct RtpTransceiverInit final {
|
||||||
|
// Direction of the RtpTransceiver. See RtpTransceiverInterface::direction().
|
||||||
|
RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv;
|
||||||
|
|
||||||
|
// The added RtpTransceiver will be added to these streams.
|
||||||
|
// TODO(bugs.webrtc.org/7600): Not implemented.
|
||||||
|
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
|
||||||
|
|
||||||
|
// TODO(bugs.webrtc.org/7600): Not implemented.
|
||||||
|
std::vector<RtpEncodingParameters> send_encodings;
|
||||||
|
};
|
||||||
|
|
||||||
// The RtpTransceiverInterface maps to the RTCRtpTransceiver defined by the
|
// The RtpTransceiverInterface maps to the RTCRtpTransceiver defined by the
|
||||||
// WebRTC specification. A transceiver represents a combination of an RtpSender
|
// WebRTC specification. A transceiver represents a combination of an RtpSender
|
||||||
// and an RtpReceiver than share a common mid. As defined in JSEP, an
|
// and an RtpReceiver than share a common mid. As defined in JSEP, an
|
||||||
|
@ -1205,6 +1205,110 @@ bool PeerConnection::RemoveTrack(RtpSenderInterface* sender) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
PeerConnection::AddTransceiver(
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
||||||
|
return AddTransceiver(track, RtpTransceiverInit());
|
||||||
|
}
|
||||||
|
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
PeerConnection::AddTransceiver(
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
|
const RtpTransceiverInit& init) {
|
||||||
|
if (!IsUnifiedPlan()) {
|
||||||
|
LOG_AND_RETURN_ERROR(
|
||||||
|
RTCErrorType::INTERNAL_ERROR,
|
||||||
|
"AddTransceiver only supported when Unified Plan is enabled.");
|
||||||
|
}
|
||||||
|
if (!track) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, "track is null");
|
||||||
|
}
|
||||||
|
cricket::MediaType media_type;
|
||||||
|
if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
|
||||||
|
media_type = cricket::MEDIA_TYPE_AUDIO;
|
||||||
|
} else if (track->kind() == MediaStreamTrackInterface::kVideoKind) {
|
||||||
|
media_type = cricket::MEDIA_TYPE_VIDEO;
|
||||||
|
} else {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
||||||
|
"Track kind is not audio or video");
|
||||||
|
}
|
||||||
|
return AddTransceiver(media_type, track, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
PeerConnection::AddTransceiver(cricket::MediaType media_type) {
|
||||||
|
return AddTransceiver(media_type, RtpTransceiverInit());
|
||||||
|
}
|
||||||
|
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
PeerConnection::AddTransceiver(cricket::MediaType media_type,
|
||||||
|
const RtpTransceiverInit& init) {
|
||||||
|
if (!IsUnifiedPlan()) {
|
||||||
|
LOG_AND_RETURN_ERROR(
|
||||||
|
RTCErrorType::INTERNAL_ERROR,
|
||||||
|
"AddTransceiver only supported when Unified Plan is enabled.");
|
||||||
|
}
|
||||||
|
if (!(media_type == cricket::MEDIA_TYPE_AUDIO ||
|
||||||
|
media_type == cricket::MEDIA_TYPE_VIDEO)) {
|
||||||
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
||||||
|
"media type is not audio or video");
|
||||||
|
}
|
||||||
|
return AddTransceiver(media_type, nullptr, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
PeerConnection::AddTransceiver(
|
||||||
|
cricket::MediaType media_type,
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
|
const RtpTransceiverInit& init) {
|
||||||
|
RTC_DCHECK((media_type == cricket::MEDIA_TYPE_AUDIO ||
|
||||||
|
media_type == cricket::MEDIA_TYPE_VIDEO));
|
||||||
|
if (track) {
|
||||||
|
RTC_DCHECK_EQ(media_type,
|
||||||
|
(track->kind() == MediaStreamTrackInterface::kAudioKind
|
||||||
|
? cricket::MEDIA_TYPE_AUDIO
|
||||||
|
: cricket::MEDIA_TYPE_VIDEO));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bugs.webrtc.org/7600): Verify init.
|
||||||
|
|
||||||
|
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender;
|
||||||
|
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
|
||||||
|
receiver;
|
||||||
|
std::string receiver_id = rtc::CreateRandomUuid();
|
||||||
|
if (media_type == cricket::MEDIA_TYPE_AUDIO) {
|
||||||
|
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
||||||
|
signaling_thread(), new AudioRtpSender(nullptr, stats_.get()));
|
||||||
|
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||||
|
signaling_thread(), new AudioRtpReceiver(receiver_id, {}, 0, nullptr));
|
||||||
|
} else {
|
||||||
|
RTC_DCHECK_EQ(cricket::MEDIA_TYPE_VIDEO, media_type);
|
||||||
|
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
|
||||||
|
signaling_thread(), new VideoRtpSender(nullptr));
|
||||||
|
receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
|
||||||
|
signaling_thread(),
|
||||||
|
new VideoRtpReceiver(receiver_id, {}, worker_thread(), 0, nullptr));
|
||||||
|
}
|
||||||
|
// TODO(bugs.webrtc.org/7600): Initializing the sender/receiver with a null
|
||||||
|
// channel prevents users from calling SetParameters on them, which is needed
|
||||||
|
// to be in compliance with the spec.
|
||||||
|
|
||||||
|
if (track) {
|
||||||
|
sender->SetTrack(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||||
|
transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
|
||||||
|
signaling_thread(), new RtpTransceiver(sender, receiver));
|
||||||
|
transceiver->SetDirection(init.direction);
|
||||||
|
|
||||||
|
transceivers_.push_back(transceiver);
|
||||||
|
|
||||||
|
observer_->OnRenegotiationNeeded();
|
||||||
|
|
||||||
|
return rtc::scoped_refptr<RtpTransceiverInterface>(transceiver);
|
||||||
|
}
|
||||||
|
|
||||||
rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
|
rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
|
||||||
AudioTrackInterface* track) {
|
AudioTrackInterface* track) {
|
||||||
TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender");
|
TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender");
|
||||||
@ -1297,6 +1401,16 @@ PeerConnection::GetReceiversInternal() const {
|
|||||||
return all_receivers;
|
return all_receivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
|
||||||
|
PeerConnection::GetTransceivers() const {
|
||||||
|
RTC_DCHECK(IsUnifiedPlan());
|
||||||
|
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> all_transceivers;
|
||||||
|
for (auto transceiver : transceivers_) {
|
||||||
|
all_transceivers.push_back(transceiver);
|
||||||
|
}
|
||||||
|
return all_transceivers;
|
||||||
|
}
|
||||||
|
|
||||||
bool PeerConnection::GetStats(StatsObserver* observer,
|
bool PeerConnection::GetStats(StatsObserver* observer,
|
||||||
MediaStreamTrackInterface* track,
|
MediaStreamTrackInterface* track,
|
||||||
StatsOutputLevel level) {
|
StatsOutputLevel level) {
|
||||||
|
@ -94,6 +94,17 @@ class PeerConnection : public PeerConnectionInterface,
|
|||||||
std::vector<MediaStreamInterface*> streams) override;
|
std::vector<MediaStreamInterface*> streams) override;
|
||||||
bool RemoveTrack(RtpSenderInterface* sender) override;
|
bool RemoveTrack(RtpSenderInterface* sender) override;
|
||||||
|
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track) override;
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
|
const RtpTransceiverInit& init) override;
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
|
||||||
|
cricket::MediaType media_type) override;
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
|
||||||
|
cricket::MediaType media_type,
|
||||||
|
const RtpTransceiverInit& init) override;
|
||||||
|
|
||||||
// Gets the DTLS SSL certificate associated with the audio transport on the
|
// Gets the DTLS SSL certificate associated with the audio transport on the
|
||||||
// remote side. This will become populated once the DTLS connection with the
|
// remote side. This will become populated once the DTLS connection with the
|
||||||
// peer has been completed, as indicated by the ICE connection state
|
// peer has been completed, as indicated by the ICE connection state
|
||||||
@ -114,6 +125,8 @@ class PeerConnection : public PeerConnectionInterface,
|
|||||||
const override;
|
const override;
|
||||||
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
|
std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
|
||||||
const override;
|
const override;
|
||||||
|
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> GetTransceivers()
|
||||||
|
const override;
|
||||||
|
|
||||||
rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
|
rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
|
||||||
const std::string& label,
|
const std::string& label,
|
||||||
@ -327,6 +340,11 @@ class PeerConnection : public PeerConnectionInterface,
|
|||||||
void RemoveVideoTrack(VideoTrackInterface* track,
|
void RemoveVideoTrack(VideoTrackInterface* track,
|
||||||
MediaStreamInterface* stream);
|
MediaStreamInterface* stream);
|
||||||
|
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> AddTransceiver(
|
||||||
|
cricket::MediaType media_type,
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
|
const RtpTransceiverInit& init);
|
||||||
|
|
||||||
void SetIceConnectionState(IceConnectionState new_state);
|
void SetIceConnectionState(IceConnectionState new_state);
|
||||||
// Called any time the IceGatheringState changes
|
// Called any time the IceGatheringState changes
|
||||||
void OnIceGatheringChange(IceGatheringState new_state);
|
void OnIceGatheringChange(IceGatheringState new_state);
|
||||||
|
@ -27,11 +27,16 @@
|
|||||||
#include "rtc_base/refcountedobject.h"
|
#include "rtc_base/refcountedobject.h"
|
||||||
#include "rtc_base/scoped_ref_ptr.h"
|
#include "rtc_base/scoped_ref_ptr.h"
|
||||||
#include "rtc_base/thread.h"
|
#include "rtc_base/thread.h"
|
||||||
|
#include "test/gmock.h"
|
||||||
|
|
||||||
// This file contains tests for RTP Media API-related behavior of
|
// This file contains tests for RTP Media API-related behavior of
|
||||||
// |webrtc::PeerConnection|, see https://w3c.github.io/webrtc-pc/#rtp-media-api.
|
// |webrtc::PeerConnection|, see https://w3c.github.io/webrtc-pc/#rtp-media-api.
|
||||||
|
|
||||||
namespace {
|
namespace webrtc {
|
||||||
|
|
||||||
|
using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
|
||||||
|
using ::testing::ElementsAre;
|
||||||
|
using ::testing::UnorderedElementsAre;
|
||||||
|
|
||||||
const uint32_t kDefaultTimeout = 10000u;
|
const uint32_t kDefaultTimeout = 10000u;
|
||||||
|
|
||||||
@ -55,28 +60,37 @@ class OnSuccessObserver : public rtc::RefCountedObject<
|
|||||||
class PeerConnectionRtpTest : public testing::Test {
|
class PeerConnectionRtpTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
PeerConnectionRtpTest()
|
PeerConnectionRtpTest()
|
||||||
: pc_factory_(webrtc::CreatePeerConnectionFactory(
|
: pc_factory_(
|
||||||
rtc::Thread::Current(),
|
CreatePeerConnectionFactory(rtc::Thread::Current(),
|
||||||
rtc::Thread::Current(),
|
rtc::Thread::Current(),
|
||||||
rtc::Thread::Current(),
|
rtc::Thread::Current(),
|
||||||
FakeAudioCaptureModule::Create(),
|
FakeAudioCaptureModule::Create(),
|
||||||
webrtc::CreateBuiltinAudioEncoderFactory(),
|
CreateBuiltinAudioEncoderFactory(),
|
||||||
webrtc::CreateBuiltinAudioDecoderFactory(),
|
CreateBuiltinAudioDecoderFactory(),
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr)) {}
|
nullptr)) {}
|
||||||
|
|
||||||
std::unique_ptr<webrtc::PeerConnectionWrapper> CreatePeerConnection() {
|
std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection() {
|
||||||
webrtc::PeerConnectionInterface::RTCConfiguration config;
|
return CreatePeerConnection(RTCConfiguration());
|
||||||
auto observer = rtc::MakeUnique<webrtc::MockPeerConnectionObserver>();
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<PeerConnectionWrapper> CreatePeerConnectionWithUnifiedPlan() {
|
||||||
|
RTCConfiguration config;
|
||||||
|
config.sdp_semantics = SdpSemantics::kUnifiedPlan;
|
||||||
|
return CreatePeerConnection(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection(
|
||||||
|
const RTCConfiguration& config) {
|
||||||
|
auto observer = rtc::MakeUnique<MockPeerConnectionObserver>();
|
||||||
auto pc = pc_factory_->CreatePeerConnection(config, nullptr, nullptr,
|
auto pc = pc_factory_->CreatePeerConnection(config, nullptr, nullptr,
|
||||||
observer.get());
|
observer.get());
|
||||||
return std::unique_ptr<webrtc::PeerConnectionWrapper>(
|
return rtc::MakeUnique<PeerConnectionWrapper>(pc_factory_, pc,
|
||||||
new webrtc::PeerConnectionWrapper(pc_factory_, pc,
|
std::move(observer));
|
||||||
std::move(observer)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
|
rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// These tests cover |webrtc::PeerConnectionObserver| callbacks firing upon
|
// These tests cover |webrtc::PeerConnectionObserver| callbacks firing upon
|
||||||
@ -87,7 +101,7 @@ TEST_F(PeerConnectionRtpCallbacksTest, AddTrackWithoutStreamFiresOnAddTrack) {
|
|||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
auto callee = CreatePeerConnection();
|
auto callee = CreatePeerConnection();
|
||||||
|
|
||||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
|
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||||
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
||||||
EXPECT_TRUE(caller->pc()->AddTrack(audio_track.get(), {}));
|
EXPECT_TRUE(caller->pc()->AddTrack(audio_track.get(), {}));
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
@ -107,9 +121,9 @@ TEST_F(PeerConnectionRtpCallbacksTest, AddTrackWithStreamFiresOnAddTrack) {
|
|||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
auto callee = CreatePeerConnection();
|
auto callee = CreatePeerConnection();
|
||||||
|
|
||||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
|
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||||
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
||||||
auto stream = webrtc::MediaStream::Create("audio_stream");
|
auto stream = MediaStream::Create("audio_stream");
|
||||||
EXPECT_TRUE(caller->pc()->AddTrack(audio_track.get(), {stream.get()}));
|
EXPECT_TRUE(caller->pc()->AddTrack(audio_track.get(), {stream.get()}));
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(),
|
callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(),
|
||||||
@ -128,7 +142,7 @@ TEST_F(PeerConnectionRtpCallbacksTest,
|
|||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
auto callee = CreatePeerConnection();
|
auto callee = CreatePeerConnection();
|
||||||
|
|
||||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
|
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||||
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
||||||
auto sender = caller->pc()->AddTrack(audio_track.get(), {});
|
auto sender = caller->pc()->AddTrack(audio_track.get(), {});
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
@ -150,9 +164,9 @@ TEST_F(PeerConnectionRtpCallbacksTest,
|
|||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
auto callee = CreatePeerConnection();
|
auto callee = CreatePeerConnection();
|
||||||
|
|
||||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
|
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||||
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
||||||
auto stream = webrtc::MediaStream::Create("audio_stream");
|
auto stream = MediaStream::Create("audio_stream");
|
||||||
auto sender = caller->pc()->AddTrack(audio_track.get(), {stream.get()});
|
auto sender = caller->pc()->AddTrack(audio_track.get(), {stream.get()});
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(),
|
callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(),
|
||||||
@ -173,12 +187,12 @@ TEST_F(PeerConnectionRtpCallbacksTest,
|
|||||||
auto caller = CreatePeerConnection();
|
auto caller = CreatePeerConnection();
|
||||||
auto callee = CreatePeerConnection();
|
auto callee = CreatePeerConnection();
|
||||||
|
|
||||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track1(
|
rtc::scoped_refptr<AudioTrackInterface> audio_track1(
|
||||||
pc_factory_->CreateAudioTrack("audio_track1", nullptr));
|
pc_factory_->CreateAudioTrack("audio_track1", nullptr));
|
||||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track2(
|
rtc::scoped_refptr<AudioTrackInterface> audio_track2(
|
||||||
pc_factory_->CreateAudioTrack("audio_track2", nullptr));
|
pc_factory_->CreateAudioTrack("audio_track2", nullptr));
|
||||||
auto stream = webrtc::MediaStream::Create("shared_audio_stream");
|
auto stream = MediaStream::Create("shared_audio_stream");
|
||||||
std::vector<webrtc::MediaStreamInterface*> streams{stream.get()};
|
std::vector<MediaStreamInterface*> streams{stream.get()};
|
||||||
auto sender1 = caller->pc()->AddTrack(audio_track1.get(), streams);
|
auto sender1 = caller->pc()->AddTrack(audio_track1.get(), streams);
|
||||||
auto sender2 = caller->pc()->AddTrack(audio_track2.get(), streams);
|
auto sender2 = caller->pc()->AddTrack(audio_track2.get(), streams);
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
@ -194,7 +208,7 @@ TEST_F(PeerConnectionRtpCallbacksTest,
|
|||||||
static_cast<webrtc::RTCError*>(nullptr)));
|
static_cast<webrtc::RTCError*>(nullptr)));
|
||||||
ASSERT_EQ(callee->observer()->add_track_events_.size(), 2u);
|
ASSERT_EQ(callee->observer()->add_track_events_.size(), 2u);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>>{
|
std::vector<rtc::scoped_refptr<RtpReceiverInterface>>{
|
||||||
callee->observer()->add_track_events_[0].receiver},
|
callee->observer()->add_track_events_[0].receiver},
|
||||||
callee->observer()->remove_track_events_);
|
callee->observer()->remove_track_events_);
|
||||||
|
|
||||||
@ -438,4 +452,146 @@ TEST_F(PeerConnectionRtpLegacyObserverTest,
|
|||||||
EXPECT_FALSE(observer->called());
|
EXPECT_FALSE(observer->called());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
// RtpTransceiver Tests
|
||||||
|
|
||||||
|
// Test that by default there are no transceivers with Unified Plan.
|
||||||
|
TEST_F(PeerConnectionRtpTest, PeerConnectionHasNoTransceivers) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
EXPECT_THAT(caller->pc()->GetTransceivers(), ElementsAre());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a transceiver created with the audio kind has the correct initial
|
||||||
|
// properties.
|
||||||
|
TEST_F(PeerConnectionRtpTest, AddTransceiverHasCorrectInitProperties) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
|
||||||
|
auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
|
||||||
|
EXPECT_EQ(rtc::nullopt, transceiver->mid());
|
||||||
|
EXPECT_FALSE(transceiver->stopped());
|
||||||
|
EXPECT_EQ(RtpTransceiverDirection::kSendRecv, transceiver->direction());
|
||||||
|
EXPECT_EQ(rtc::nullopt, transceiver->current_direction());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that adding a transceiver with the audio kind creates an audio sender
|
||||||
|
// and audio receiver with the receiver having a live audio track.
|
||||||
|
TEST_F(PeerConnectionRtpTest,
|
||||||
|
AddAudioTransceiverCreatesAudioSenderAndReceiver) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
|
||||||
|
auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
|
||||||
|
|
||||||
|
ASSERT_TRUE(transceiver->sender());
|
||||||
|
EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, transceiver->sender()->media_type());
|
||||||
|
|
||||||
|
ASSERT_TRUE(transceiver->receiver());
|
||||||
|
EXPECT_EQ(cricket::MEDIA_TYPE_AUDIO, transceiver->receiver()->media_type());
|
||||||
|
|
||||||
|
auto track = transceiver->receiver()->track();
|
||||||
|
ASSERT_TRUE(track);
|
||||||
|
EXPECT_EQ(MediaStreamTrackInterface::kAudioKind, track->kind());
|
||||||
|
EXPECT_EQ(MediaStreamTrackInterface::TrackState::kLive, track->state());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that adding a transceiver with the video kind creates an video sender
|
||||||
|
// and video receiver with the receiver having a live video track.
|
||||||
|
TEST_F(PeerConnectionRtpTest,
|
||||||
|
AddAudioTransceiverCreatesVideoSenderAndReceiver) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
|
||||||
|
auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_VIDEO);
|
||||||
|
|
||||||
|
ASSERT_TRUE(transceiver->sender());
|
||||||
|
EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, transceiver->sender()->media_type());
|
||||||
|
|
||||||
|
ASSERT_TRUE(transceiver->receiver());
|
||||||
|
EXPECT_EQ(cricket::MEDIA_TYPE_VIDEO, transceiver->receiver()->media_type());
|
||||||
|
|
||||||
|
auto track = transceiver->receiver()->track();
|
||||||
|
ASSERT_TRUE(track);
|
||||||
|
EXPECT_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
|
||||||
|
EXPECT_EQ(MediaStreamTrackInterface::TrackState::kLive, track->state());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that after a call to AddTransceiver, the transceiver shows in
|
||||||
|
// GetTransceivers(), the transceiver's sender shows in GetSenders(), and the
|
||||||
|
// transceiver's receiver shows in GetReceivers().
|
||||||
|
TEST_F(PeerConnectionRtpTest, AddTransceiverShowsInLists) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
|
||||||
|
auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
|
||||||
|
EXPECT_EQ(
|
||||||
|
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>{transceiver},
|
||||||
|
caller->pc()->GetTransceivers());
|
||||||
|
EXPECT_EQ(
|
||||||
|
std::vector<rtc::scoped_refptr<RtpSenderInterface>>{
|
||||||
|
transceiver->sender()},
|
||||||
|
caller->pc()->GetSenders());
|
||||||
|
EXPECT_EQ(
|
||||||
|
std::vector<rtc::scoped_refptr<RtpReceiverInterface>>{
|
||||||
|
transceiver->receiver()},
|
||||||
|
caller->pc()->GetReceivers());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that the direction passed in through the AddTransceiver init parameter
|
||||||
|
// is set in the returned transceiver.
|
||||||
|
TEST_F(PeerConnectionRtpTest, AddTransceiverWithDirectionIsReflected) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
|
||||||
|
RtpTransceiverInit init;
|
||||||
|
init.direction = RtpTransceiverDirection::kSendOnly;
|
||||||
|
auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, init);
|
||||||
|
EXPECT_EQ(RtpTransceiverDirection::kSendOnly, transceiver->direction());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PeerConnectionRtpTest, AddTransceiverWithInvalidKindReturnsError) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
|
||||||
|
auto result = caller->pc()->AddTransceiver(cricket::MEDIA_TYPE_DATA);
|
||||||
|
EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that calling AddTransceiver with a track creates a transceiver which has
|
||||||
|
// its sender's track set to the passed-in track.
|
||||||
|
TEST_F(PeerConnectionRtpTest, AddTransceiverWithTrackCreatesSenderWithTrack) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
|
||||||
|
auto audio_track = caller->CreateAudioTrack("audio track");
|
||||||
|
auto transceiver = caller->AddTransceiver(audio_track);
|
||||||
|
|
||||||
|
auto sender = transceiver->sender();
|
||||||
|
ASSERT_TRUE(sender->track());
|
||||||
|
EXPECT_EQ(audio_track, sender->track());
|
||||||
|
|
||||||
|
auto receiver = transceiver->receiver();
|
||||||
|
ASSERT_TRUE(receiver->track());
|
||||||
|
EXPECT_EQ(MediaStreamTrackInterface::kAudioKind, receiver->track()->kind());
|
||||||
|
EXPECT_EQ(MediaStreamTrackInterface::TrackState::kLive,
|
||||||
|
receiver->track()->state());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that calling AddTransceiver twice with the same track creates distinct
|
||||||
|
// transceivers, senders with the same track.
|
||||||
|
TEST_F(PeerConnectionRtpTest,
|
||||||
|
AddTransceiverTwiceWithSameTrackCreatesMultipleTransceivers) {
|
||||||
|
auto caller = CreatePeerConnectionWithUnifiedPlan();
|
||||||
|
|
||||||
|
auto audio_track = caller->CreateAudioTrack("audio track");
|
||||||
|
|
||||||
|
auto transceiver1 = caller->AddTransceiver(audio_track);
|
||||||
|
auto transceiver2 = caller->AddTransceiver(audio_track);
|
||||||
|
|
||||||
|
EXPECT_NE(transceiver1, transceiver2);
|
||||||
|
|
||||||
|
auto sender1 = transceiver1->sender();
|
||||||
|
auto sender2 = transceiver2->sender();
|
||||||
|
EXPECT_NE(sender1, sender2);
|
||||||
|
EXPECT_EQ(audio_track, sender1->track());
|
||||||
|
EXPECT_EQ(audio_track, sender2->track());
|
||||||
|
|
||||||
|
EXPECT_THAT(caller->pc()->GetTransceivers(),
|
||||||
|
UnorderedElementsAre(transceiver1, transceiver2));
|
||||||
|
EXPECT_THAT(caller->pc()->GetSenders(),
|
||||||
|
UnorderedElementsAre(sender1, sender2));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
@ -179,22 +179,64 @@ bool PeerConnectionWrapper::SetSdp(
|
|||||||
return observer->result();
|
return observer->result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc::scoped_refptr<RtpTransceiverInterface>
|
||||||
|
PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type) {
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
|
||||||
|
pc()->AddTransceiver(media_type);
|
||||||
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
||||||
|
return result.MoveValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::scoped_refptr<RtpTransceiverInterface>
|
||||||
|
PeerConnectionWrapper::AddTransceiver(cricket::MediaType media_type,
|
||||||
|
const RtpTransceiverInit& init) {
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
|
||||||
|
pc()->AddTransceiver(media_type, init);
|
||||||
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
||||||
|
return result.MoveValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::scoped_refptr<RtpTransceiverInterface>
|
||||||
|
PeerConnectionWrapper::AddTransceiver(
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
|
||||||
|
pc()->AddTransceiver(track);
|
||||||
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
||||||
|
return result.MoveValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::scoped_refptr<RtpTransceiverInterface>
|
||||||
|
PeerConnectionWrapper::AddTransceiver(
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
|
const RtpTransceiverInit& init) {
|
||||||
|
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
|
||||||
|
pc()->AddTransceiver(track, init);
|
||||||
|
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
||||||
|
return result.MoveValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::scoped_refptr<AudioTrackInterface> PeerConnectionWrapper::CreateAudioTrack(
|
||||||
|
const std::string& label) {
|
||||||
|
return pc_factory()->CreateAudioTrack(label, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::scoped_refptr<VideoTrackInterface> PeerConnectionWrapper::CreateVideoTrack(
|
||||||
|
const std::string& label) {
|
||||||
|
auto video_source = pc_factory()->CreateVideoSource(
|
||||||
|
rtc::MakeUnique<cricket::FakeVideoCapturer>());
|
||||||
|
return pc_factory()->CreateVideoTrack(label, video_source);
|
||||||
|
}
|
||||||
|
|
||||||
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddAudioTrack(
|
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddAudioTrack(
|
||||||
const std::string& track_label,
|
const std::string& track_label,
|
||||||
std::vector<MediaStreamInterface*> streams) {
|
std::vector<MediaStreamInterface*> streams) {
|
||||||
auto media_stream_track =
|
return pc()->AddTrack(CreateAudioTrack(track_label), std::move(streams));
|
||||||
pc_factory()->CreateAudioTrack(track_label, nullptr);
|
|
||||||
return pc()->AddTrack(media_stream_track, std::move(streams));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddVideoTrack(
|
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddVideoTrack(
|
||||||
const std::string& track_label,
|
const std::string& track_label,
|
||||||
std::vector<MediaStreamInterface*> streams) {
|
std::vector<MediaStreamInterface*> streams) {
|
||||||
auto video_source = pc_factory()->CreateVideoSource(
|
return pc()->AddTrack(CreateVideoTrack(track_label), std::move(streams));
|
||||||
rtc::MakeUnique<cricket::FakeVideoCapturer>());
|
|
||||||
auto media_stream_track =
|
|
||||||
pc_factory()->CreateVideoTrack(track_label, video_source);
|
|
||||||
return pc()->AddTrack(media_stream_track, std::move(streams));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerConnectionInterface::SignalingState
|
PeerConnectionInterface::SignalingState
|
||||||
|
@ -93,6 +93,28 @@ class PeerConnectionWrapper {
|
|||||||
bool SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc,
|
bool SetRemoteDescription(std::unique_ptr<SessionDescriptionInterface> desc,
|
||||||
RTCError* error_out);
|
RTCError* error_out);
|
||||||
|
|
||||||
|
// The following are wrappers for the underlying PeerConnection's
|
||||||
|
// AddTransceiver method. They return the result of calling AddTransceiver
|
||||||
|
// with the given arguments, DCHECKing if there is an error.
|
||||||
|
rtc::scoped_refptr<RtpTransceiverInterface> AddTransceiver(
|
||||||
|
cricket::MediaType media_type);
|
||||||
|
rtc::scoped_refptr<RtpTransceiverInterface> AddTransceiver(
|
||||||
|
cricket::MediaType media_type,
|
||||||
|
const RtpTransceiverInit& init);
|
||||||
|
rtc::scoped_refptr<RtpTransceiverInterface> AddTransceiver(
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track);
|
||||||
|
rtc::scoped_refptr<RtpTransceiverInterface> AddTransceiver(
|
||||||
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||||
|
const RtpTransceiverInit& init);
|
||||||
|
|
||||||
|
// Returns a new dummy audio track with the given label.
|
||||||
|
rtc::scoped_refptr<AudioTrackInterface> CreateAudioTrack(
|
||||||
|
const std::string& label);
|
||||||
|
|
||||||
|
// Returns a new dummy video track with the given label.
|
||||||
|
rtc::scoped_refptr<VideoTrackInterface> CreateVideoTrack(
|
||||||
|
const std::string& label);
|
||||||
|
|
||||||
// Calls the underlying PeerConnection's AddTrack method with an audio media
|
// Calls the underlying PeerConnection's AddTrack method with an audio media
|
||||||
// stream track not bound to any source.
|
// stream track not bound to any source.
|
||||||
rtc::scoped_refptr<RtpSenderInterface> AddAudioTrack(
|
rtc::scoped_refptr<RtpSenderInterface> AddAudioTrack(
|
||||||
|
@ -22,16 +22,16 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
AudioRtpReceiver::AudioRtpReceiver(
|
AudioRtpReceiver::AudioRtpReceiver(
|
||||||
const std::string& track_id,
|
const std::string& receiver_id,
|
||||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
|
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
|
||||||
uint32_t ssrc,
|
uint32_t ssrc,
|
||||||
cricket::VoiceChannel* channel)
|
cricket::VoiceChannel* channel)
|
||||||
: id_(track_id),
|
: id_(receiver_id),
|
||||||
ssrc_(ssrc),
|
ssrc_(ssrc),
|
||||||
channel_(channel),
|
channel_(channel),
|
||||||
track_(AudioTrackProxy::Create(
|
track_(AudioTrackProxy::Create(
|
||||||
rtc::Thread::Current(),
|
rtc::Thread::Current(),
|
||||||
AudioTrack::Create(track_id,
|
AudioTrack::Create(receiver_id,
|
||||||
RemoteAudioSource::Create(ssrc, channel)))),
|
RemoteAudioSource::Create(ssrc, channel)))),
|
||||||
streams_(std::move(streams)),
|
streams_(std::move(streams)),
|
||||||
cached_track_enabled_(track_->enabled()) {
|
cached_track_enabled_(track_->enabled()) {
|
||||||
|
@ -50,11 +50,10 @@ class AudioRtpReceiver : public ObserverInterface,
|
|||||||
// TODO(deadbeef): Use rtc::Optional, or have another constructor that
|
// TODO(deadbeef): Use rtc::Optional, or have another constructor that
|
||||||
// doesn't take an SSRC, and make this one DCHECK(ssrc != 0).
|
// doesn't take an SSRC, and make this one DCHECK(ssrc != 0).
|
||||||
AudioRtpReceiver(
|
AudioRtpReceiver(
|
||||||
const std::string& track_id,
|
const std::string& receiver_id,
|
||||||
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
|
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
|
||||||
uint32_t ssrc,
|
uint32_t ssrc,
|
||||||
cricket::VoiceChannel* channel);
|
cricket::VoiceChannel* channel);
|
||||||
|
|
||||||
virtual ~AudioRtpReceiver();
|
virtual ~AudioRtpReceiver();
|
||||||
|
|
||||||
// ObserverInterface implementation
|
// ObserverInterface implementation
|
||||||
|
Reference in New Issue
Block a user