Add support for enabling simulcast in "Plan B" using MediaConstraints.
BUG=webrtc:9655 Change-Id: Ieb5fe5d97b6d4381608a51593bca5423979d1b9f Reviewed-on: https://webrtc-review.googlesource.com/95481 Commit-Queue: Jonas Oreland <jonaso@webrtc.org> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Reviewed-by: Seth Hampson <shampson@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24424}
This commit is contained in:

committed by
Commit Bot

parent
d65e143801
commit
fc1acd2364
@ -146,6 +146,9 @@ const char MediaConstraintsInterface::kCpuOveruseDetection[] =
|
||||
"googCpuOveruseDetection";
|
||||
const char MediaConstraintsInterface::kPayloadPadding[] = "googPayloadPadding";
|
||||
|
||||
const char MediaConstraintsInterface::kNumSimulcastLayers[] =
|
||||
"googNumSimulcastLayers";
|
||||
|
||||
// Set |value| to the value associated with the first appearance of |key|, or
|
||||
// return false if |key| is not found.
|
||||
bool MediaConstraintsInterface::Constraints::FindFirst(
|
||||
@ -301,6 +304,13 @@ bool CopyConstraintsIntoOfferAnswerOptions(
|
||||
offer_answer_options->ice_restart = value;
|
||||
}
|
||||
|
||||
int layers;
|
||||
if (FindConstraint(constraints,
|
||||
MediaConstraintsInterface::kNumSimulcastLayers,
|
||||
&layers, &mandatory_constraints_satisfied)) {
|
||||
offer_answer_options->num_simulcast_layers = layers;
|
||||
}
|
||||
|
||||
return mandatory_constraints_satisfied == constraints->GetMandatory().size();
|
||||
}
|
||||
|
||||
|
@ -119,6 +119,11 @@ class MediaConstraintsInterface {
|
||||
// stripped by Chrome before passed down to Libjingle.
|
||||
static const char kInternalConstraintPrefix[];
|
||||
|
||||
// Specifies number of simulcast layers for all video tracks
|
||||
// with a Plan B offer/answer
|
||||
// (see RTCOfferAnswerOptions::num_simulcast_layers).
|
||||
static const char kNumSimulcastLayers[];
|
||||
|
||||
virtual ~MediaConstraintsInterface() = default;
|
||||
|
||||
virtual const Constraints& GetMandatory() const = 0;
|
||||
|
@ -596,6 +596,9 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
|
||||
// confused with RTCP mux (multiplexing RTP and RTCP together).
|
||||
bool use_rtp_mux = true;
|
||||
|
||||
// This will apply to all video tracks with a Plan B SDP offer/answer.
|
||||
int num_simulcast_layers = 1;
|
||||
|
||||
RTCOfferAnswerOptions() = default;
|
||||
|
||||
RTCOfferAnswerOptions(int offer_to_receive_video,
|
||||
|
@ -173,7 +173,8 @@ void AddRtpSenderOptions(
|
||||
const std::vector<rtc::scoped_refptr<
|
||||
RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders,
|
||||
cricket::MediaDescriptionOptions* audio_media_description_options,
|
||||
cricket::MediaDescriptionOptions* video_media_description_options) {
|
||||
cricket::MediaDescriptionOptions* video_media_description_options,
|
||||
int num_sim_layers) {
|
||||
for (const auto& sender : senders) {
|
||||
if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
|
||||
if (audio_media_description_options) {
|
||||
@ -184,7 +185,8 @@ void AddRtpSenderOptions(
|
||||
RTC_DCHECK(sender->media_type() == cricket::MEDIA_TYPE_VIDEO);
|
||||
if (video_media_description_options) {
|
||||
video_media_description_options->AddVideoSender(
|
||||
sender->id(), sender->internal()->stream_ids(), 1);
|
||||
sender->id(), sender->internal()->stream_ids(),
|
||||
num_sim_layers);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3686,7 +3688,8 @@ void PeerConnection::GetOptionsForPlanBOffer(
|
||||
: &session_options->media_description_options[*video_index];
|
||||
|
||||
AddRtpSenderOptions(GetSendersInternal(), audio_media_description_options,
|
||||
video_media_description_options);
|
||||
video_media_description_options,
|
||||
offer_answer_options.num_simulcast_layers);
|
||||
}
|
||||
|
||||
// Find a new MID that is not already in |used_mids|, then add it to |used_mids|
|
||||
@ -3910,7 +3913,8 @@ void PeerConnection::GetOptionsForPlanBAnswer(
|
||||
: &session_options->media_description_options[*video_index];
|
||||
|
||||
AddRtpSenderOptions(GetSendersInternal(), audio_media_description_options,
|
||||
video_media_description_options);
|
||||
video_media_description_options,
|
||||
offer_answer_options.num_simulcast_layers);
|
||||
}
|
||||
|
||||
void PeerConnection::GetOptionsForUnifiedPlanAnswer(
|
||||
|
@ -273,6 +273,56 @@ TEST_F(PeerConnectionMediaTestPlanB, EmptyRemoteOfferRemovesRecvStreams) {
|
||||
EXPECT_EQ(0u, callee_video->recv_streams().size());
|
||||
}
|
||||
|
||||
// Test enabling of simulcast with Plan B semantics.
|
||||
// This test creating an offer.
|
||||
TEST_F(PeerConnectionMediaTestPlanB, SimulcastOffer) {
|
||||
auto caller = CreatePeerConnection();
|
||||
auto caller_video_track = caller->AddVideoTrack("v");
|
||||
RTCOfferAnswerOptions options;
|
||||
options.num_simulcast_layers = 3;
|
||||
auto offer = caller->CreateOffer(options);
|
||||
auto* description = cricket::GetFirstMediaContent(
|
||||
offer->description(),
|
||||
cricket::MEDIA_TYPE_VIDEO)->media_description();
|
||||
ASSERT_EQ(1u, description->streams().size());
|
||||
ASSERT_TRUE(description->streams()[0].get_ssrc_group("SIM"));
|
||||
EXPECT_EQ(3u, description->streams()[0].get_ssrc_group("SIM")->ssrcs.size());
|
||||
|
||||
// Check that it actually creates simulcast aswell.
|
||||
caller->SetLocalDescription(std::move(offer));
|
||||
auto senders = caller->pc()->GetSenders();
|
||||
ASSERT_EQ(1u, senders.size());
|
||||
EXPECT_EQ(cricket::MediaType::MEDIA_TYPE_VIDEO, senders[0]->media_type());
|
||||
EXPECT_EQ(3u, senders[0]->GetParameters().encodings.size());
|
||||
}
|
||||
|
||||
// Test enabling of simulcast with Plan B semantics.
|
||||
// This test creating an answer.
|
||||
TEST_F(PeerConnectionMediaTestPlanB, SimulcastAnswer) {
|
||||
auto caller = CreatePeerConnection();
|
||||
caller->AddVideoTrack("v0");
|
||||
auto offer = caller->CreateOffer();
|
||||
auto callee = CreatePeerConnection();
|
||||
auto callee_video_track = callee->AddVideoTrack("v1");
|
||||
ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
|
||||
RTCOfferAnswerOptions options;
|
||||
options.num_simulcast_layers = 3;
|
||||
auto answer = callee->CreateAnswer(options);
|
||||
auto* description = cricket::GetFirstMediaContent(
|
||||
answer->description(),
|
||||
cricket::MEDIA_TYPE_VIDEO)->media_description();
|
||||
ASSERT_EQ(1u, description->streams().size());
|
||||
ASSERT_TRUE(description->streams()[0].get_ssrc_group("SIM"));
|
||||
EXPECT_EQ(3u, description->streams()[0].get_ssrc_group("SIM")->ssrcs.size());
|
||||
|
||||
// Check that it actually creates simulcast aswell.
|
||||
callee->SetLocalDescription(std::move(answer));
|
||||
auto senders = callee->pc()->GetSenders();
|
||||
ASSERT_EQ(1u, senders.size());
|
||||
EXPECT_EQ(cricket::MediaType::MEDIA_TYPE_VIDEO, senders[0]->media_type());
|
||||
EXPECT_EQ(3u, senders[0]->GetParameters().encodings.size());
|
||||
}
|
||||
|
||||
// Test that stopping the callee transceivers causes the media channels to be
|
||||
// destroyed on the callee after calling SetLocalDescription on the local
|
||||
// answer.
|
||||
|
Reference in New Issue
Block a user