Improve spec compliance of SetStreamIDs in RtpSenderInterface

This CL makes RtpSender::SetStreamIDs fire fire negotiationneeded
event if needed and exposes the method on RtpSenderInterface.

This is a spec-compliance change.

Bug: webrtc:10129
Change-Id: I2b98b92665c847102838b094516a79b24de0e47e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135121
Commit-Queue: Guido Urdaneta <guidou@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27974}
This commit is contained in:
Guido Urdaneta 2019-05-17 14:23:05 +02:00 committed by Commit Bot
parent 519d74a5fc
commit df5731e44d
8 changed files with 157 additions and 83 deletions

View file

@ -61,6 +61,11 @@ class RtpSenderInterface : public rtc::RefCountInterface {
// tracks.
virtual std::vector<std::string> stream_ids() const = 0;
// Sets the IDs of the media streams associated with this sender's track.
// These are signalled in the SDP so that the remote side can associate
// tracks.
virtual void SetStreamIDs(const std::vector<std::string>& stream_ids) {}
// Returns the list of encoding parameters that will be applied when the SDP
// local description is set. These initial encoding parameters can be set by
// PeerConnection::AddTransceiver, and later updated with Get/SetParameters.
@ -112,6 +117,7 @@ PROXY_METHOD1(void,
rtc::scoped_refptr<FrameEncryptorInterface>)
PROXY_CONSTMETHOD0(rtc::scoped_refptr<FrameEncryptorInterface>,
GetFrameEncryptor)
PROXY_METHOD1(void, SetStreamIDs, const std::vector<std::string>&)
END_PROXY_MAP()
} // namespace webrtc

View file

@ -1373,7 +1373,7 @@ PeerConnection::AddTrackUnifiedPlan(
RtpTransceiverDirection::kSendOnly);
}
transceiver->sender()->SetTrack(track);
transceiver->internal()->sender_internal()->set_stream_ids(stream_ids);
transceiver->internal()->sender_internal()->SetStreamIDs(stream_ids);
} else {
cricket::MediaType media_type =
(track->kind() == MediaStreamTrackInterface::kAudioKind
@ -1632,19 +1632,19 @@ PeerConnection::CreateSender(
(track->kind() == MediaStreamTrackInterface::kAudioKind));
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
signaling_thread(),
AudioRtpSender::Create(worker_thread(), id, stats_.get()));
AudioRtpSender::Create(worker_thread(), id, stats_.get(), this));
NoteUsageEvent(UsageEvent::AUDIO_ADDED);
} else {
RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
RTC_DCHECK(!track ||
(track->kind() == MediaStreamTrackInterface::kVideoKind));
sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
signaling_thread(), VideoRtpSender::Create(worker_thread(), id));
signaling_thread(), VideoRtpSender::Create(worker_thread(), id, this));
NoteUsageEvent(UsageEvent::VIDEO_ADDED);
}
bool set_track_succeeded = sender->SetTrack(track);
RTC_DCHECK(set_track_succeeded);
sender->internal()->set_stream_ids(stream_ids);
sender->internal()->SetStreamIDs(stream_ids);
sender->internal()->set_init_send_encodings(send_encodings);
return sender;
}
@ -1722,14 +1722,14 @@ rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> new_sender;
if (kind == MediaStreamTrackInterface::kAudioKind) {
auto audio_sender = AudioRtpSender::Create(
worker_thread(), rtc::CreateRandomUuid(), stats_.get());
worker_thread(), rtc::CreateRandomUuid(), stats_.get(), this);
audio_sender->SetMediaChannel(voice_media_channel());
new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
signaling_thread(), audio_sender);
GetAudioTransceiver()->internal()->AddSender(new_sender);
} else if (kind == MediaStreamTrackInterface::kVideoKind) {
auto video_sender =
VideoRtpSender::Create(worker_thread(), rtc::CreateRandomUuid());
VideoRtpSender::Create(worker_thread(), rtc::CreateRandomUuid(), this);
video_sender->SetMediaChannel(video_media_channel());
new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
signaling_thread(), video_sender);
@ -1738,7 +1738,7 @@ rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
RTC_LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
return nullptr;
}
new_sender->internal()->set_stream_ids(stream_ids);
new_sender->internal()->SetStreamIDs(stream_ids);
return new_sender;
}
@ -2361,7 +2361,7 @@ RTCError PeerConnection::ApplyLocalDescription(
} else {
// Get the StreamParams from the channel which could generate SSRCs.
const std::vector<StreamParams>& streams = channel->local_streams();
transceiver->internal()->sender_internal()->set_stream_ids(
transceiver->internal()->sender_internal()->SetStreamIDs(
streams[0].stream_ids());
transceiver->internal()->sender_internal()->SetSsrc(
streams[0].first_ssrc());
@ -4010,7 +4010,7 @@ void PeerConnection::AddAudioTrack(AudioTrackInterface* track,
if (sender) {
// We already have a sender for this track, so just change the stream_id
// so that it's correct in the next call to CreateOffer.
sender->internal()->set_stream_ids({stream->id()});
sender->internal()->SetStreamIDs({stream->id()});
return;
}
@ -4055,7 +4055,7 @@ void PeerConnection::AddVideoTrack(VideoTrackInterface* track,
if (sender) {
// We already have a sender for this track, so just change the stream_id
// so that it's correct in the next call to CreateOffer.
sender->internal()->set_stream_ids({stream->id()});
sender->internal()->SetStreamIDs({stream->id()});
return;
}
@ -4987,7 +4987,7 @@ void PeerConnection::OnLocalSenderAdded(const RtpSenderInfo& sender_info,
return;
}
sender->internal()->set_stream_ids({sender_info.stream_id});
sender->internal()->SetStreamIDs({sender_info.stream_id});
sender->internal()->SetSsrc(sender_info.first_ssrc);
}
@ -7130,6 +7130,12 @@ bool PeerConnection::OnTransportChanged(
return ret;
}
void PeerConnection::OnSetStreamIDs() {
RTC_DCHECK_RUN_ON(signaling_thread());
if (IsUnifiedPlan())
UpdateNegotiationNeeded();
}
PeerConnectionObserver* PeerConnection::Observer() const {
// In earlier production code, the pointer was not cleared on close,
// which might have led to undefined behavior if the observer was not

View file

@ -25,6 +25,7 @@
#include "pc/peer_connection_factory.h"
#include "pc/peer_connection_internal.h"
#include "pc/rtc_stats_collector.h"
#include "pc/rtp_sender.h"
#include "pc/rtp_transceiver.h"
#include "pc/sctp_transport.h"
#include "pc/stats_collector.h"
@ -57,6 +58,7 @@ class PeerConnection : public PeerConnectionInternal,
public DataChannelProviderInterface,
public DataChannelSink,
public JsepTransportController::Observer,
public RtpSenderBase::SetStreamIDsObserver,
public rtc::MessageHandler,
public sigslot::has_slots<> {
public:
@ -1055,6 +1057,9 @@ class PeerConnection : public PeerConnectionInternal,
rtc::scoped_refptr<DtlsTransport> dtls_transport,
MediaTransportInterface* media_transport) override;
// RtpSenderBase::SetStreamIDsObserver override.
void OnSetStreamIDs() override;
// Returns the observer. Will crash on CHECK if the observer is removed.
PeerConnectionObserver* Observer() const RTC_RUN_ON(signaling_thread());

View file

@ -491,15 +491,8 @@ TEST_F(PeerConnectionRtpTestUnifiedPlan, ChangeMsidWhileReceiving) {
ASSERT_TRUE(callee->CreateAnswerAndSetAsLocal());
// Change the stream ID in the offer.
// TODO(https://crbug.com/webrtc/10129): When RtpSenderInterface::SetStreams
// is supported, this can use that instead of munging the SDP.
auto offer = caller->CreateOffer();
auto contents = offer->description()->contents();
ASSERT_EQ(1u, contents.size());
auto& stream_params = contents[0].media_description()->mutable_streams();
ASSERT_EQ(1u, stream_params.size());
stream_params[0].set_stream_ids({"stream2"});
ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
caller->pc()->GetSenders()[0]->SetStreamIDs({"stream2"});
ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
ASSERT_EQ(1u, transceiver->receiver()->streams().size());
EXPECT_EQ("stream2", transceiver->receiver()->streams()[0]->id());
}
@ -1797,12 +1790,7 @@ TEST_P(PeerConnectionRtpTest, CreateTwoSendersWithSameTrack) {
// This test exercises the code path that fires a NegotiationNeeded
// notification when the stream IDs of the local description differ from
// the ones in the transceiver. Since SetStreams() is not yet available
// on RtpSenderInterface, adding a track is used to trigger the check for
// the NegotiationNeeded notification.
// TODO(https://crbug.com/webrtc/10129): Replace this test with a test that
// checks that calling SetStreams() on a sender fires the notification once
// the method becomes available in RtpSenderInterface.
// the ones in the transceiver.
TEST_F(PeerConnectionRtpTestUnifiedPlan,
ChangeAssociatedStreamsTriggersRenegotiation) {
auto caller = CreatePeerConnection();
@ -1817,18 +1805,15 @@ TEST_F(PeerConnectionRtpTestUnifiedPlan,
ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
caller->observer()->clear_negotiation_needed();
SessionDescriptionInterface* cld = const_cast<SessionDescriptionInterface*>(
caller->pc()->current_local_description());
ASSERT_EQ(cld->description()->contents().size(), 1u);
cricket::SessionDescription* description = cld->description();
cricket::ContentInfo& content_info = description->contents()[0];
ASSERT_EQ(content_info.media_description()->mutable_streams().size(), 1u);
content_info.media_description()->mutable_streams()[0].set_stream_ids(
{"stream3", "stream4", "stream5"});
ASSERT_TRUE(caller->AddTrack(caller->CreateAudioTrack("a2")));
transceiver->sender()->SetStreamIDs({"stream3", "stream4", "stream5"});
EXPECT_TRUE(caller->observer()->negotiation_needed());
ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
auto callee_streams = callee->pc()->GetReceivers()[0]->streams();
ASSERT_EQ(3u, callee_streams.size());
EXPECT_EQ("stream3", callee_streams[0]->id());
EXPECT_EQ("stream4", callee_streams[1]->id());
EXPECT_EQ("stream5", callee_streams[2]->id());
}
INSTANTIATE_TEST_SUITE_P(PeerConnectionRtpTest,

View file

@ -16,6 +16,7 @@
#include "api/audio_options.h"
#include "api/media_stream_interface.h"
#include "media/base/media_engine.h"
#include "pc/peer_connection.h"
#include "pc/stats_collector.h"
#include "rtc_base/checks.h"
#include "rtc_base/helpers.h"
@ -118,8 +119,12 @@ bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters) {
return false;
}
RtpSenderBase::RtpSenderBase(rtc::Thread* worker_thread, const std::string& id)
: worker_thread_(worker_thread), id_(id) {
RtpSenderBase::RtpSenderBase(rtc::Thread* worker_thread,
const std::string& id,
SetStreamIDsObserver* set_stream_ids_observer)
: worker_thread_(worker_thread),
id_(id),
set_stream_ids_observer_(set_stream_ids_observer) {
RTC_DCHECK(worker_thread);
init_parameters_.encodings.emplace_back();
}
@ -215,6 +220,12 @@ RTCError RtpSenderBase::SetParameters(const RtpParameters& parameters) {
return result;
}
void RtpSenderBase::SetStreamIDs(const std::vector<std::string>& stream_ids) {
stream_ids_ = stream_ids;
if (set_stream_ids_observer_)
set_stream_ids_observer_->OnSetStreamIDs();
}
bool RtpSenderBase::SetTrack(MediaStreamTrackInterface* track) {
TRACE_EVENT0("webrtc", "RtpSenderBase::SetTrack");
if (stopped_) {
@ -317,6 +328,7 @@ void RtpSenderBase::Stop() {
RemoveTrackFromStats();
}
media_channel_ = nullptr;
set_stream_ids_observer_ = nullptr;
stopped_ = true;
}
@ -395,15 +407,18 @@ void LocalAudioSinkAdapter::SetSink(cricket::AudioSource::Sink* sink) {
rtc::scoped_refptr<AudioRtpSender> AudioRtpSender::Create(
rtc::Thread* worker_thread,
const std::string& id,
StatsCollector* stats) {
StatsCollector* stats,
SetStreamIDsObserver* set_stream_ids_observer) {
return rtc::scoped_refptr<AudioRtpSender>(
new rtc::RefCountedObject<AudioRtpSender>(worker_thread, id, stats));
new rtc::RefCountedObject<AudioRtpSender>(worker_thread, id, stats,
set_stream_ids_observer));
}
AudioRtpSender::AudioRtpSender(rtc::Thread* worker_thread,
const std::string& id,
StatsCollector* stats)
: RtpSenderBase(worker_thread, id),
StatsCollector* stats,
SetStreamIDsObserver* set_stream_ids_observer)
: RtpSenderBase(worker_thread, id, set_stream_ids_observer),
stats_(stats),
dtmf_sender_proxy_(DtmfSenderProxy::Create(
rtc::Thread::Current(),
@ -539,14 +554,17 @@ void AudioRtpSender::ClearSend() {
rtc::scoped_refptr<VideoRtpSender> VideoRtpSender::Create(
rtc::Thread* worker_thread,
const std::string& id) {
const std::string& id,
SetStreamIDsObserver* set_stream_ids_observer) {
return rtc::scoped_refptr<VideoRtpSender>(
new rtc::RefCountedObject<VideoRtpSender>(worker_thread, id));
new rtc::RefCountedObject<VideoRtpSender>(worker_thread, id,
set_stream_ids_observer));
}
VideoRtpSender::VideoRtpSender(rtc::Thread* worker_thread,
const std::string& id)
: RtpSenderBase(worker_thread, id) {}
const std::string& id,
SetStreamIDsObserver* set_stream_ids_observer)
: RtpSenderBase(worker_thread, id, set_stream_ids_observer) {}
VideoRtpSender::~VideoRtpSender() {
Stop();

View file

@ -47,7 +47,7 @@ class RtpSenderInternal : public RtpSenderInterface {
// description).
virtual void SetSsrc(uint32_t ssrc) = 0;
virtual void set_stream_ids(const std::vector<std::string>& stream_ids) = 0;
virtual void SetStreamIDs(const std::vector<std::string>& stream_ids) {}
virtual void set_init_send_encodings(
const std::vector<RtpEncodingParameters>& init_send_encodings) = 0;
virtual void set_transport(
@ -74,6 +74,12 @@ class RtpSenderInternal : public RtpSenderInterface {
// Shared implementation for RtpSenderInternal interface.
class RtpSenderBase : public RtpSenderInternal, public ObserverInterface {
public:
class SetStreamIDsObserver {
public:
virtual ~SetStreamIDsObserver() = default;
virtual void OnSetStreamIDs() = 0;
};
// Sets the underlying MediaEngine channel associated with this RtpSender.
// A VoiceMediaChannel should be used for audio RtpSenders and
// a VideoMediaChannel should be used for video RtpSenders.
@ -101,9 +107,7 @@ class RtpSenderBase : public RtpSenderInternal, public ObserverInterface {
uint32_t ssrc() const override { return ssrc_; }
std::vector<std::string> stream_ids() const override { return stream_ids_; }
void set_stream_ids(const std::vector<std::string>& stream_ids) override {
stream_ids_ = stream_ids;
}
void SetStreamIDs(const std::vector<std::string>& stream_ids) override;
std::string id() const override { return id_; }
@ -143,7 +147,12 @@ class RtpSenderBase : public RtpSenderInternal, public ObserverInterface {
RTCError DisableEncodingLayers(const std::vector<std::string>& rid) override;
protected:
RtpSenderBase(rtc::Thread* worker_thread, const std::string& id);
// If |set_stream_ids_observer| is not null, it is invoked when SetStreamIDs
// is called. |set_stream_ids_observer| is not owned by this object. If not
// null, it must be valid at least until this sender becomes stopped.
RtpSenderBase(rtc::Thread* worker_thread,
const std::string& id,
SetStreamIDsObserver* set_stream_ids_observer);
// TODO(nisse): Since SSRC == 0 is technically valid, figure out
// some other way to test if we have a valid SSRC.
bool can_send_track() const { return track_ && ssrc_; }
@ -183,6 +192,8 @@ class RtpSenderBase : public RtpSenderInternal, public ObserverInterface {
// const method.
mutable absl::optional<std::string> last_transaction_id_;
std::vector<std::string> disabled_rids_;
SetStreamIDsObserver* set_stream_ids_observer_ = nullptr;
};
// LocalAudioSinkAdapter receives data callback as a sink to the local
@ -215,9 +226,14 @@ class AudioRtpSender : public DtmfProviderInterface, public RtpSenderBase {
// The sender is initialized with no track to send and no associated streams.
// StatsCollector provided so that Add/RemoveLocalAudioTrack can be called
// at the appropriate times.
static rtc::scoped_refptr<AudioRtpSender> Create(rtc::Thread* worker_thread,
const std::string& id,
StatsCollector* stats);
// If |set_stream_ids_observer| is not null, it is invoked when SetStreamIDs
// is called. |set_stream_ids_observer| is not owned by this object. If not
// null, it must be valid at least until this sender becomes stopped.
static rtc::scoped_refptr<AudioRtpSender> Create(
rtc::Thread* worker_thread,
const std::string& id,
StatsCollector* stats,
SetStreamIDsObserver* set_stream_ids_observer);
virtual ~AudioRtpSender();
// DtmfSenderProvider implementation.
@ -240,7 +256,8 @@ class AudioRtpSender : public DtmfProviderInterface, public RtpSenderBase {
protected:
AudioRtpSender(rtc::Thread* worker_thread,
const std::string& id,
StatsCollector* stats);
StatsCollector* stats,
SetStreamIDsObserver* set_stream_ids_observer);
void SetSend() override;
void ClearSend() override;
@ -274,8 +291,13 @@ class VideoRtpSender : public RtpSenderBase {
public:
// Construct an RtpSender for video with the given sender ID.
// The sender is initialized with no track to send and no associated streams.
static rtc::scoped_refptr<VideoRtpSender> Create(rtc::Thread* worker_thread,
const std::string& id);
// If |set_stream_ids_observer| is not null, it is invoked when SetStreamIDs
// is called. |set_stream_ids_observer| is not owned by this object. If not
// null, it must be valid at least until this sender becomes stopped.
static rtc::scoped_refptr<VideoRtpSender> Create(
rtc::Thread* worker_thread,
const std::string& id,
SetStreamIDsObserver* set_stream_ids_observer);
virtual ~VideoRtpSender();
// ObserverInterface implementation
@ -291,7 +313,9 @@ class VideoRtpSender : public RtpSenderBase {
rtc::scoped_refptr<DtmfSenderInterface> GetDtmfSender() const override;
protected:
VideoRtpSender(rtc::Thread* worker_thread, const std::string& id);
VideoRtpSender(rtc::Thread* worker_thread,
const std::string& id,
SetStreamIDsObserver* set_stream_ids_observer);
void SetSend() override;
void ClearSend() override;

View file

@ -83,6 +83,13 @@ static const uint32_t kAudioSsrc2 = 101;
static const uint32_t kVideoSsrcSimulcast = 102;
static const uint32_t kVideoSimulcastLayerCount = 2;
static const int kDefaultTimeout = 10000; // 10 seconds.
class MockSetStreamIDsObserver
: public webrtc::RtpSenderBase::SetStreamIDsObserver {
public:
MOCK_METHOD0(OnSetStreamIDs, void());
};
} // namespace
namespace webrtc {
@ -187,10 +194,14 @@ class RtpSenderReceiverTest
const rtc::scoped_refptr<LocalAudioSource>& source) {
audio_track_ = AudioTrack::Create(kAudioTrackId, source);
EXPECT_TRUE(local_stream_->AddTrack(audio_track_));
std::unique_ptr<MockSetStreamIDsObserver> set_stream_ids_observer =
absl::make_unique<MockSetStreamIDsObserver>();
audio_rtp_sender_ =
AudioRtpSender::Create(worker_thread_, audio_track_->id(), nullptr);
AudioRtpSender::Create(worker_thread_, audio_track_->id(), nullptr,
set_stream_ids_observer.get());
ASSERT_TRUE(audio_rtp_sender_->SetTrack(audio_track_));
audio_rtp_sender_->set_stream_ids({local_stream_->id()});
EXPECT_CALL(*set_stream_ids_observer, OnSetStreamIDs());
audio_rtp_sender_->SetStreamIDs({local_stream_->id()});
audio_rtp_sender_->SetMediaChannel(voice_media_channel_);
audio_rtp_sender_->SetSsrc(kAudioSsrc);
audio_rtp_sender_->GetOnDestroyedSignal()->connect(
@ -200,7 +211,7 @@ class RtpSenderReceiverTest
void CreateAudioRtpSenderWithNoTrack() {
audio_rtp_sender_ =
AudioRtpSender::Create(worker_thread_, /*id=*/"", nullptr);
AudioRtpSender::Create(worker_thread_, /*id=*/"", nullptr, nullptr);
audio_rtp_sender_->SetMediaChannel(voice_media_channel_);
}
@ -248,16 +259,20 @@ class RtpSenderReceiverTest
void CreateVideoRtpSender(bool is_screencast, uint32_t ssrc = kVideoSsrc) {
AddVideoTrack(is_screencast);
video_rtp_sender_ =
VideoRtpSender::Create(worker_thread_, video_track_->id());
std::unique_ptr<MockSetStreamIDsObserver> set_stream_ids_observer =
absl::make_unique<MockSetStreamIDsObserver>();
video_rtp_sender_ = VideoRtpSender::Create(
worker_thread_, video_track_->id(), set_stream_ids_observer.get());
ASSERT_TRUE(video_rtp_sender_->SetTrack(video_track_));
video_rtp_sender_->set_stream_ids({local_stream_->id()});
EXPECT_CALL(*set_stream_ids_observer, OnSetStreamIDs());
video_rtp_sender_->SetStreamIDs({local_stream_->id()});
video_rtp_sender_->SetMediaChannel(video_media_channel_);
video_rtp_sender_->SetSsrc(ssrc);
VerifyVideoChannelInput(ssrc);
}
void CreateVideoRtpSenderWithNoTrack() {
video_rtp_sender_ = VideoRtpSender::Create(worker_thread_, /*id=*/"");
video_rtp_sender_ =
VideoRtpSender::Create(worker_thread_, /*id=*/"", nullptr);
video_rtp_sender_->SetMediaChannel(video_media_channel_);
}
@ -428,7 +443,7 @@ class RtpSenderReceiverTest
void RunDisableSimulcastLayersWithoutMediaEngineTest(
const std::vector<std::string>& all_layers,
const std::vector<std::string>& disabled_layers) {
auto sender = VideoRtpSender::Create(rtc::Thread::Current(), "1");
auto sender = VideoRtpSender::Create(rtc::Thread::Current(), "1", nullptr);
RtpParameters parameters;
parameters.encodings.resize(all_layers.size());
for (size_t i = 0; i < all_layers.size(); ++i) {
@ -820,7 +835,7 @@ TEST_F(RtpSenderReceiverTest, AudioSenderCanSetParameters) {
TEST_F(RtpSenderReceiverTest, AudioSenderCanSetParametersBeforeNegotiation) {
audio_rtp_sender_ =
AudioRtpSender::Create(worker_thread_, /*id=*/"", nullptr);
AudioRtpSender::Create(worker_thread_, /*id=*/"", nullptr, nullptr);
RtpParameters params = audio_rtp_sender_->GetParameters();
ASSERT_EQ(1u, params.encodings.size());
@ -838,10 +853,14 @@ TEST_F(RtpSenderReceiverTest, AudioSenderInitParametersMovedAfterNegotiation) {
audio_track_ = AudioTrack::Create(kAudioTrackId, nullptr);
EXPECT_TRUE(local_stream_->AddTrack(audio_track_));
std::unique_ptr<MockSetStreamIDsObserver> set_stream_ids_observer =
absl::make_unique<MockSetStreamIDsObserver>();
audio_rtp_sender_ =
AudioRtpSender::Create(worker_thread_, audio_track_->id(), nullptr);
AudioRtpSender::Create(worker_thread_, audio_track_->id(), nullptr,
set_stream_ids_observer.get());
ASSERT_TRUE(audio_rtp_sender_->SetTrack(audio_track_));
audio_rtp_sender_->set_stream_ids({local_stream_->id()});
EXPECT_CALL(*set_stream_ids_observer, OnSetStreamIDs());
audio_rtp_sender_->SetStreamIDs({local_stream_->id()});
std::vector<RtpEncodingParameters> init_encodings(1);
init_encodings[0].max_bitrate_bps = 60000;
@ -869,7 +888,7 @@ TEST_F(RtpSenderReceiverTest, AudioSenderInitParametersMovedAfterNegotiation) {
TEST_F(RtpSenderReceiverTest,
AudioSenderMustCallGetParametersBeforeSetParametersBeforeNegotiation) {
audio_rtp_sender_ =
AudioRtpSender::Create(worker_thread_, /*id=*/"", nullptr);
AudioRtpSender::Create(worker_thread_, /*id=*/"", nullptr, nullptr);
RtpParameters params;
RTCError result = audio_rtp_sender_->SetParameters(params);
@ -1048,7 +1067,8 @@ TEST_F(RtpSenderReceiverTest, VideoSenderCanSetParameters) {
}
TEST_F(RtpSenderReceiverTest, VideoSenderCanSetParametersBeforeNegotiation) {
video_rtp_sender_ = VideoRtpSender::Create(worker_thread_, /*id=*/"");
video_rtp_sender_ =
VideoRtpSender::Create(worker_thread_, /*id=*/"", nullptr);
RtpParameters params = video_rtp_sender_->GetParameters();
ASSERT_EQ(1u, params.encodings.size());
@ -1065,10 +1085,13 @@ TEST_F(RtpSenderReceiverTest, VideoSenderCanSetParametersBeforeNegotiation) {
TEST_F(RtpSenderReceiverTest, VideoSenderInitParametersMovedAfterNegotiation) {
AddVideoTrack(false);
video_rtp_sender_ =
VideoRtpSender::Create(worker_thread_, video_track_->id());
std::unique_ptr<MockSetStreamIDsObserver> set_stream_ids_observer =
absl::make_unique<MockSetStreamIDsObserver>();
video_rtp_sender_ = VideoRtpSender::Create(worker_thread_, video_track_->id(),
set_stream_ids_observer.get());
ASSERT_TRUE(video_rtp_sender_->SetTrack(video_track_));
video_rtp_sender_->set_stream_ids({local_stream_->id()});
EXPECT_CALL(*set_stream_ids_observer, OnSetStreamIDs());
video_rtp_sender_->SetStreamIDs({local_stream_->id()});
std::vector<RtpEncodingParameters> init_encodings(2);
init_encodings[0].max_bitrate_bps = 60000;
@ -1103,10 +1126,13 @@ TEST_F(RtpSenderReceiverTest,
VideoSenderInitParametersMovedAfterManualSimulcastAndNegotiation) {
AddVideoTrack(false);
video_rtp_sender_ =
VideoRtpSender::Create(worker_thread_, video_track_->id());
std::unique_ptr<MockSetStreamIDsObserver> set_stream_ids_observer =
absl::make_unique<MockSetStreamIDsObserver>();
video_rtp_sender_ = VideoRtpSender::Create(worker_thread_, video_track_->id(),
set_stream_ids_observer.get());
ASSERT_TRUE(video_rtp_sender_->SetTrack(video_track_));
video_rtp_sender_->set_stream_ids({local_stream_->id()});
EXPECT_CALL(*set_stream_ids_observer, OnSetStreamIDs());
video_rtp_sender_->SetStreamIDs({local_stream_->id()});
std::vector<RtpEncodingParameters> init_encodings(1);
init_encodings[0].max_bitrate_bps = 60000;
@ -1137,7 +1163,8 @@ TEST_F(RtpSenderReceiverTest,
TEST_F(RtpSenderReceiverTest,
VideoSenderMustCallGetParametersBeforeSetParametersBeforeNegotiation) {
video_rtp_sender_ = VideoRtpSender::Create(worker_thread_, /*id=*/"");
video_rtp_sender_ =
VideoRtpSender::Create(worker_thread_, /*id=*/"", nullptr);
RtpParameters params;
RTCError result = video_rtp_sender_->SetParameters(params);
@ -1527,13 +1554,16 @@ TEST_F(RtpSenderReceiverTest,
TEST_F(RtpSenderReceiverTest,
PropagatesVideoTrackContentHintSetBeforeEnabling) {
AddVideoTrack();
std::unique_ptr<MockSetStreamIDsObserver> set_stream_ids_observer =
absl::make_unique<MockSetStreamIDsObserver>();
// Setting detailed overrides the default non-screencast mode. This should be
// applied even if the track is set on construction.
video_track_->set_content_hint(VideoTrackInterface::ContentHint::kDetailed);
video_rtp_sender_ =
VideoRtpSender::Create(worker_thread_, video_track_->id());
video_rtp_sender_ = VideoRtpSender::Create(worker_thread_, video_track_->id(),
set_stream_ids_observer.get());
ASSERT_TRUE(video_rtp_sender_->SetTrack(video_track_));
video_rtp_sender_->set_stream_ids({local_stream_->id()});
EXPECT_CALL(*set_stream_ids_observer, OnSetStreamIDs());
video_rtp_sender_->SetStreamIDs({local_stream_->id()});
video_rtp_sender_->SetMediaChannel(video_media_channel_);
video_track_->set_enabled(true);

View file

@ -46,7 +46,7 @@ class MockRtpSenderInternal : public RtpSenderInternal {
// RtpSenderInternal methods.
MOCK_METHOD1(SetMediaChannel, void(cricket::MediaChannel*));
MOCK_METHOD1(SetSsrc, void(uint32_t));
MOCK_METHOD1(set_stream_ids, void(const std::vector<std::string>&));
MOCK_METHOD1(SetStreamIDs, void(const std::vector<std::string>&));
MOCK_METHOD1(set_init_send_encodings,
void(const std::vector<RtpEncodingParameters>&));
MOCK_METHOD0(Stop, void());