Add optional init_send_encodings to AddTrack
This patch adds variant of PeerConnectionInterface::AddTrack that takes an initial_send_encodings. This allows for setting/modifying encoding parameters before sdp negotiation is performed/complete (e.g requested_resolution). This is already available if using RtpTransciverInit and AddTransceiver, but was not added to AddTrack because of concerns that it complicated matching with existing transceivers. This CL sidesteps that by never matching to a preexisting transceiver if initial_send_encodings are specified. Note: 1) The patch adds a new method rather than an extra (e.g optional) argument to existing AddTrack. This is to avoid problems with downstream mocks. 2) chromium "problems" was fixed in https://chromium-review.googlesource.com/c/chromium/src/+/3952684 and https://chromium-review.googlesource.com/c/chromium/src/+/3956060 Bug: webrtc:14451 Change-Id: I19b5a03872730280fbf868ca5d3a2f46443359f3 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/278783 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Jonas Oreland <jonaso@webrtc.org> Cr-Commit-Position: refs/heads/main@{#38437}
This commit is contained in:
parent
5a92577a94
commit
4b2a106af2
@ -804,6 +804,16 @@ class RTC_EXPORT PeerConnectionInterface : public rtc::RefCountInterface {
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) = 0;
|
||||
|
||||
// Add a new MediaStreamTrack as above, but with an additional parameter,
|
||||
// `init_send_encodings` : initial RtpEncodingParameters for RtpSender,
|
||||
// similar to init_send_encodings in RtpTransceiverInit.
|
||||
// Note that a new transceiver will always be created.
|
||||
//
|
||||
virtual 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) = 0;
|
||||
|
||||
// Removes the connection between a MediaStreamTrack and the PeerConnection.
|
||||
// Stops sending on the RtpSender and marks the
|
||||
// corresponding RtpTransceiver direction as no longer sending.
|
||||
|
||||
@ -47,6 +47,12 @@ class MockPeerConnectionInterface : public webrtc::PeerConnectionInterface {
|
||||
(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>),
|
||||
|
||||
@ -836,6 +836,20 @@ void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
return AddTrack(std::move(track), stream_ids, nullptr);
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>& init_send_encodings) {
|
||||
return AddTrack(std::move(track), stream_ids, &init_send_encodings);
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
TRACE_EVENT0("webrtc", "PeerConnection::AddTrack");
|
||||
if (!ConfiguredForMedia()) {
|
||||
@ -859,7 +873,8 @@ RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::AddTrack(
|
||||
RTCErrorType::INVALID_PARAMETER,
|
||||
"Sender already exists for track " + track->id() + ".");
|
||||
}
|
||||
auto sender_or_error = rtp_manager()->AddTrack(track, stream_ids);
|
||||
auto sender_or_error =
|
||||
rtp_manager()->AddTrack(track, stream_ids, init_send_encodings);
|
||||
if (sender_or_error.ok()) {
|
||||
sdp_handler_->UpdateNegotiationNeeded();
|
||||
legacy_stats_->AddTrack(track.get());
|
||||
|
||||
@ -129,6 +129,14 @@ class PeerConnection : public PeerConnectionInternal,
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) override;
|
||||
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;
|
||||
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);
|
||||
RTCError RemoveTrackOrError(
|
||||
rtc::scoped_refptr<RtpSenderInterface> sender) override;
|
||||
|
||||
|
||||
@ -441,7 +441,9 @@ class RtcEventLogOutputNull final : public RtcEventLogOutput {
|
||||
};
|
||||
|
||||
using ::cricket::StreamParams;
|
||||
using ::testing::Eq;
|
||||
using ::testing::Exactly;
|
||||
using ::testing::SizeIs;
|
||||
using ::testing::Values;
|
||||
|
||||
using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
|
||||
@ -1580,6 +1582,57 @@ TEST_F(PeerConnectionInterfaceTestPlanB, AddTrackRemoveTrack) {
|
||||
EXPECT_FALSE(pc_->RemoveTrackOrError(video_sender).ok());
|
||||
}
|
||||
|
||||
// Test for AddTrack with init_send_encoding.
|
||||
TEST_F(PeerConnectionInterfaceTestPlanB, AddTrackWithSendEncodings) {
|
||||
CreatePeerConnectionWithoutDtls();
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||
CreateAudioTrack("audio_track"));
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track(
|
||||
CreateVideoTrack("video_track"));
|
||||
RtpEncodingParameters audio_encodings;
|
||||
audio_encodings.active = false;
|
||||
auto audio_sender =
|
||||
pc_->AddTrack(audio_track, {kStreamId1}, {audio_encodings}).MoveValue();
|
||||
RtpEncodingParameters video_encodings;
|
||||
video_encodings.active = true;
|
||||
auto video_sender =
|
||||
pc_->AddTrack(video_track, {kStreamId1}, {video_encodings}).MoveValue();
|
||||
EXPECT_EQ(1UL, audio_sender->stream_ids().size());
|
||||
EXPECT_EQ(kStreamId1, audio_sender->stream_ids()[0]);
|
||||
EXPECT_EQ("audio_track", audio_sender->id());
|
||||
EXPECT_EQ(audio_track, audio_sender->track());
|
||||
EXPECT_EQ(1UL, video_sender->stream_ids().size());
|
||||
EXPECT_EQ(kStreamId1, video_sender->stream_ids()[0]);
|
||||
EXPECT_EQ("video_track", video_sender->id());
|
||||
EXPECT_EQ(video_track, video_sender->track());
|
||||
|
||||
// Now create an offer and check for the senders.
|
||||
std::unique_ptr<SessionDescriptionInterface> offer;
|
||||
ASSERT_TRUE(DoCreateOffer(&offer, nullptr));
|
||||
|
||||
const cricket::ContentInfo* audio_content =
|
||||
cricket::GetFirstAudioContent(offer->description());
|
||||
EXPECT_TRUE(ContainsTrack(audio_content->media_description()->streams(),
|
||||
kStreamId1, "audio_track"));
|
||||
|
||||
const cricket::ContentInfo* video_content =
|
||||
cricket::GetFirstVideoContent(offer->description());
|
||||
EXPECT_TRUE(ContainsTrack(video_content->media_description()->streams(),
|
||||
kStreamId1, "video_track"));
|
||||
|
||||
EXPECT_TRUE(DoSetLocalDescription(std::move(offer)));
|
||||
|
||||
// Check the encodings.
|
||||
ASSERT_THAT(audio_sender->GetParameters().encodings, SizeIs(1));
|
||||
EXPECT_THAT(audio_sender->GetParameters().encodings[0].active, Eq(false));
|
||||
ASSERT_THAT(video_sender->GetParameters().encodings, SizeIs(1));
|
||||
EXPECT_THAT(video_sender->GetParameters().encodings[0].active, Eq(true));
|
||||
|
||||
// Now try removing the tracks.
|
||||
EXPECT_TRUE(pc_->RemoveTrackOrError(audio_sender).ok());
|
||||
EXPECT_TRUE(pc_->RemoveTrackOrError(video_sender).ok());
|
||||
}
|
||||
|
||||
// Test creating senders without a stream specified,
|
||||
// expecting a random stream ID to be generated.
|
||||
TEST_P(PeerConnectionInterfaceTest, AddTrackWithoutStream) {
|
||||
|
||||
@ -35,6 +35,11 @@ PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>,
|
||||
AddTrack,
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface>,
|
||||
const std::vector<std::string>&)
|
||||
PROXY_METHOD3(RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>,
|
||||
AddTrack,
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface>,
|
||||
const std::vector<std::string>&,
|
||||
const std::vector<RtpEncodingParameters>&)
|
||||
PROXY_METHOD1(RTCError,
|
||||
RemoveTrackOrError,
|
||||
rtc::scoped_refptr<RtpSenderInterface>)
|
||||
|
||||
@ -1145,6 +1145,23 @@ TEST_F(PeerConnectionRtpTestUnifiedPlan, AddTrackReusesTransceiver) {
|
||||
EXPECT_EQ(audio_track, sender->track());
|
||||
}
|
||||
|
||||
TEST_F(PeerConnectionRtpTestUnifiedPlan,
|
||||
AddTrackWithSendEncodingDoesNotReuseTransceiver) {
|
||||
auto caller = CreatePeerConnection();
|
||||
|
||||
auto transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
|
||||
auto audio_track = caller->CreateAudioTrack("a");
|
||||
RtpEncodingParameters encoding;
|
||||
auto sender = caller->AddTrack(audio_track, {}, {encoding});
|
||||
ASSERT_TRUE(sender);
|
||||
|
||||
auto transceivers = caller->pc()->GetTransceivers();
|
||||
ASSERT_EQ(2u, transceivers.size());
|
||||
EXPECT_EQ(transceiver, transceivers[0]);
|
||||
EXPECT_NE(sender, transceiver->sender());
|
||||
EXPECT_EQ(audio_track, sender->track());
|
||||
}
|
||||
|
||||
// Test that adding two tracks to a new PeerConnection creates two
|
||||
// RtpTransceivers in the same order.
|
||||
TEST_F(PeerConnectionRtpTestUnifiedPlan, TwoAddTrackCreatesTwoTransceivers) {
|
||||
|
||||
@ -289,6 +289,16 @@ rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
|
||||
return result.MoveValue();
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>& init_send_encodings) {
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
|
||||
pc()->AddTrack(track, stream_ids, init_send_encodings);
|
||||
EXPECT_EQ(RTCErrorType::NONE, result.error().type());
|
||||
return result.MoveValue();
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<RtpSenderInterface> PeerConnectionWrapper::AddAudioTrack(
|
||||
const std::string& track_label,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
|
||||
@ -149,6 +149,11 @@ class PeerConnectionWrapper {
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids = {});
|
||||
|
||||
rtc::scoped_refptr<RtpSenderInterface> AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>& init_send_encodings);
|
||||
|
||||
// Calls the underlying PeerConnection's AddTrack method with an audio media
|
||||
// stream track not bound to any source.
|
||||
rtc::scoped_refptr<RtpSenderInterface> AddAudioTrack(
|
||||
|
||||
@ -99,17 +99,20 @@ cricket::VideoMediaChannel* RtpTransmissionManager::video_media_channel()
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
||||
RtpTransmissionManager::AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
|
||||
return (IsUnifiedPlan() ? AddTrackUnifiedPlan(track, stream_ids)
|
||||
: AddTrackPlanB(track, stream_ids));
|
||||
return (IsUnifiedPlan()
|
||||
? AddTrackUnifiedPlan(track, stream_ids, init_send_encodings)
|
||||
: AddTrackPlanB(track, stream_ids, init_send_encodings));
|
||||
}
|
||||
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
||||
RtpTransmissionManager::AddTrackPlanB(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
if (stream_ids.size() > 1u) {
|
||||
LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
|
||||
@ -125,7 +128,9 @@ RtpTransmissionManager::AddTrackPlanB(
|
||||
? cricket::MEDIA_TYPE_AUDIO
|
||||
: cricket::MEDIA_TYPE_VIDEO);
|
||||
auto new_sender =
|
||||
CreateSender(media_type, track->id(), track, adjusted_stream_ids, {});
|
||||
CreateSender(media_type, track->id(), track, adjusted_stream_ids,
|
||||
init_send_encodings ? *init_send_encodings
|
||||
: std::vector<RtpEncodingParameters>());
|
||||
if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
|
||||
new_sender->internal()->SetMediaChannel(voice_media_channel());
|
||||
GetAudioTransceiver()->internal()->AddSender(new_sender);
|
||||
@ -152,8 +157,10 @@ RtpTransmissionManager::AddTrackPlanB(
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
|
||||
RtpTransmissionManager::AddTrackUnifiedPlan(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids) {
|
||||
auto transceiver = FindFirstTransceiverForAddedTrack(track);
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings) {
|
||||
auto transceiver =
|
||||
FindFirstTransceiverForAddedTrack(track, init_send_encodings);
|
||||
if (transceiver) {
|
||||
RTC_LOG(LS_INFO) << "Reusing an existing "
|
||||
<< cricket::MediaTypeToString(transceiver->media_type())
|
||||
@ -187,7 +194,10 @@ RtpTransmissionManager::AddTrackUnifiedPlan(
|
||||
if (FindSenderById(sender_id)) {
|
||||
sender_id = rtc::CreateRandomUuid();
|
||||
}
|
||||
auto sender = CreateSender(media_type, sender_id, track, stream_ids, {});
|
||||
auto sender = CreateSender(media_type, sender_id, track, stream_ids,
|
||||
init_send_encodings
|
||||
? *init_send_encodings
|
||||
: std::vector<RtpEncodingParameters>());
|
||||
auto receiver = CreateReceiver(media_type, rtc::CreateRandomUuid());
|
||||
transceiver = CreateAndAddTransceiver(sender, receiver);
|
||||
transceiver->internal()->set_created_by_addtrack(true);
|
||||
@ -280,9 +290,13 @@ RtpTransmissionManager::CreateAndAddTransceiver(
|
||||
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
RtpTransmissionManager::FindFirstTransceiverForAddedTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track) {
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings) {
|
||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||
RTC_DCHECK(track);
|
||||
if (init_send_encodings != nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
for (auto transceiver : transceivers()->List()) {
|
||||
if (!transceiver->sender()->track() &&
|
||||
cricket::MediaTypeToString(transceiver->media_type()) ==
|
||||
|
||||
@ -95,7 +95,8 @@ class RtpTransmissionManager : public RtpSenderBase::SetStreamsObserver {
|
||||
// Add a new track, creating transceiver if required.
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids);
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings);
|
||||
|
||||
// Create a new RTP sender. Does not associate with a transceiver.
|
||||
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
|
||||
@ -121,7 +122,8 @@ class RtpTransmissionManager : public RtpSenderBase::SetStreamsObserver {
|
||||
// transceiver is available.
|
||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||
FindFirstTransceiverForAddedTrack(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track);
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings);
|
||||
|
||||
// Returns the list of senders currently associated with some
|
||||
// registered transceiver
|
||||
@ -220,11 +222,13 @@ class RtpTransmissionManager : public RtpSenderBase::SetStreamsObserver {
|
||||
// AddTrack implementation when Unified Plan is specified.
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrackUnifiedPlan(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids);
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings);
|
||||
// AddTrack implementation when Plan B is specified.
|
||||
RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrackPlanB(
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
||||
const std::vector<std::string>& stream_ids);
|
||||
const std::vector<std::string>& stream_ids,
|
||||
const std::vector<RtpEncodingParameters>* init_send_encodings);
|
||||
|
||||
// Create an RtpReceiver that sources an audio track.
|
||||
void CreateAudioReceiver(MediaStreamInterface* stream,
|
||||
|
||||
@ -50,6 +50,13 @@ class FakePeerConnectionBase : public PeerConnectionInternal {
|
||||
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);
|
||||
|
||||
@ -42,6 +42,12 @@ class MockPeerConnectionInternal : public PeerConnectionInternal {
|
||||
(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>),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user