Bug 1290948 - Part 4: Transceivers JSEP/SDP work. r+drno r=drno

MozReview-Commit-ID: JwK3It3UA5M

--HG--
extra : rebase_source : e1a5afa85ed544ab0acac08240b6007954e289e4
This commit is contained in:
Byron Campen [:bwc] 2017-08-23 15:55:05 -05:00
Родитель cf90c6a366
Коммит 46f6fa03a6
17 изменённых файлов: 3190 добавлений и 2348 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -16,7 +16,12 @@ namespace mozilla {
class JsepTrackTest : public ::testing::Test
{
public:
JsepTrackTest() {}
JsepTrackTest() :
mSendOff(SdpMediaSection::kAudio, sdp::kSend),
mRecvOff(SdpMediaSection::kAudio, sdp::kRecv),
mSendAns(SdpMediaSection::kAudio, sdp::kSend),
mRecvAns(SdpMediaSection::kAudio, sdp::kRecv)
{}
std::vector<JsepCodecDescription*>
MakeCodecs(bool addFecCodecs = false,
@ -103,35 +108,52 @@ class JsepTrackTest : public ::testing::Test
void InitTracks(SdpMediaSection::MediaType type)
{
mSendOff = new JsepTrack(type, "stream_id", "track_id", sdp::kSend);
mRecvOff = new JsepTrack(type, "stream_id", "track_id", sdp::kRecv);
mSendOff->PopulateCodecs(mOffCodecs.values);
mRecvOff->PopulateCodecs(mOffCodecs.values);
mSendOff = JsepTrack(type, sdp::kSend);
if (type != SdpMediaSection::MediaType::kApplication) {
mSendOff.UpdateTrackIds(
std::vector<std::string>(1, "stream_id"), "track_id");
}
mRecvOff = JsepTrack(type, sdp::kRecv);
mSendOff.PopulateCodecs(mOffCodecs.values);
mRecvOff.PopulateCodecs(mOffCodecs.values);
mSendAns = new JsepTrack(type, "stream_id", "track_id", sdp::kSend);
mRecvAns = new JsepTrack(type, "stream_id", "track_id", sdp::kRecv);
mSendAns->PopulateCodecs(mAnsCodecs.values);
mRecvAns->PopulateCodecs(mAnsCodecs.values);
mSendAns = JsepTrack(type, sdp::kSend);
if (type != SdpMediaSection::MediaType::kApplication) {
mSendAns.UpdateTrackIds(
std::vector<std::string>(1, "stream_id"), "track_id");
}
mRecvAns = JsepTrack(type, sdp::kRecv);
mSendAns.PopulateCodecs(mAnsCodecs.values);
mRecvAns.PopulateCodecs(mAnsCodecs.values);
}
void InitSdp(SdpMediaSection::MediaType type)
{
std::vector<std::string> msids(1, "*");
std::string error;
SdpHelper helper(&error);
mOffer.reset(new SipccSdp(SdpOrigin("", 0, 0, sdp::kIPv4, "")));
mOffer->AddMediaSection(
type,
SdpDirectionAttribute::kInactive,
SdpDirectionAttribute::kSendrecv,
0,
SdpHelper::GetProtocolForMediaType(type),
sdp::kIPv4,
"0.0.0.0");
// JsepTrack doesn't set msid-semantic
helper.SetupMsidSemantic(msids, mOffer.get());
mAnswer.reset(new SipccSdp(SdpOrigin("", 0, 0, sdp::kIPv4, "")));
mAnswer->AddMediaSection(
type,
SdpDirectionAttribute::kInactive,
SdpDirectionAttribute::kSendrecv,
0,
SdpHelper::GetProtocolForMediaType(type),
sdp::kIPv4,
"0.0.0.0");
// JsepTrack doesn't set msid-semantic
helper.SetupMsidSemantic(msids, mAnswer.get());
}
SdpMediaSection& GetOffer()
@ -146,24 +168,18 @@ class JsepTrackTest : public ::testing::Test
void CreateOffer()
{
if (mSendOff) {
mSendOff->AddToOffer(&GetOffer());
}
if (mRecvOff) {
mRecvOff->AddToOffer(&GetOffer());
}
mSendOff.AddToOffer(mSsrcGenerator, &GetOffer());
mRecvOff.AddToOffer(mSsrcGenerator, &GetOffer());
}
void CreateAnswer()
{
if (mSendAns && GetOffer().IsReceiving()) {
mSendAns->AddToAnswer(GetOffer(), &GetAnswer());
if (mRecvAns.GetMediaType() != SdpMediaSection::MediaType::kApplication) {
mRecvAns.UpdateRecvTrack(*mOffer, GetOffer());
}
if (mRecvAns && GetOffer().IsSending()) {
mRecvAns->AddToAnswer(GetOffer(), &GetAnswer());
}
mSendAns.AddToAnswer(GetOffer(), mSsrcGenerator, &GetAnswer());
mRecvAns.AddToAnswer(GetOffer(), mSsrcGenerator, &GetAnswer());
}
void Negotiate()
@ -174,20 +190,18 @@ class JsepTrackTest : public ::testing::Test
std::cerr << "Answer SDP: " << std::endl;
mAnswer->Serialize(std::cerr);
if (mSendAns && GetAnswer().IsSending()) {
mSendAns->Negotiate(GetAnswer(), GetOffer());
if (mRecvOff.GetMediaType() != SdpMediaSection::MediaType::kApplication) {
mRecvOff.UpdateRecvTrack(*mAnswer, GetAnswer());
}
if (mRecvAns && GetAnswer().IsReceiving()) {
mRecvAns->Negotiate(GetAnswer(), GetOffer());
if (GetAnswer().IsSending()) {
mSendAns.Negotiate(GetAnswer(), GetOffer());
mRecvOff.Negotiate(GetAnswer(), GetAnswer());
}
if (mSendOff && GetAnswer().IsReceiving()) {
mSendOff->Negotiate(GetAnswer(), GetAnswer());
}
if (mRecvOff && GetAnswer().IsSending()) {
mRecvOff->Negotiate(GetAnswer(), GetAnswer());
if (GetAnswer().IsReceiving()) {
mRecvAns.Negotiate(GetAnswer(), GetOffer());
mSendOff.Negotiate(GetAnswer(), GetAnswer());
}
}
@ -199,32 +213,25 @@ class JsepTrackTest : public ::testing::Test
SanityCheck();
}
static size_t EncodingCount(const RefPtr<JsepTrack>& track)
{
return track->GetNegotiatedDetails()->GetEncodingCount();
}
// TODO: Look into writing a macro that wraps an ASSERT_ and returns false
// if it fails (probably requires writing a bool-returning function that
// takes a void-returning lambda with a bool outparam, which will in turn
// invokes the ASSERT_)
static void CheckEncodingCount(size_t expected,
const RefPtr<JsepTrack>& send,
const RefPtr<JsepTrack>& recv)
const JsepTrack& send,
const JsepTrack& recv)
{
if (expected) {
ASSERT_TRUE(!!send);
ASSERT_TRUE(send->GetNegotiatedDetails());
ASSERT_TRUE(!!recv);
ASSERT_TRUE(recv->GetNegotiatedDetails());
ASSERT_TRUE(send.GetNegotiatedDetails());
ASSERT_TRUE(recv.GetNegotiatedDetails());
}
if (send && send->GetNegotiatedDetails()) {
ASSERT_EQ(expected, send->GetNegotiatedDetails()->GetEncodingCount());
if (!send.GetTrackId().empty() && send.GetNegotiatedDetails()) {
ASSERT_EQ(expected, send.GetNegotiatedDetails()->GetEncodingCount());
}
if (recv && recv->GetNegotiatedDetails()) {
ASSERT_EQ(expected, recv->GetNegotiatedDetails()->GetEncodingCount());
if (!recv.GetTrackId().empty() && recv.GetNegotiatedDetails()) {
ASSERT_EQ(expected, recv.GetNegotiatedDetails()->GetEncodingCount());
}
}
@ -314,6 +321,7 @@ class JsepTrackTest : public ::testing::Test
if (a.mType != SdpMediaSection::kApplication) {
ASSERT_EQ(a.mDefaultPt, b.mDefaultPt);
}
std::cerr << a.mName << " vs " << b.mName << std::endl;
ASSERT_EQ(a.mName, b.mName);
ASSERT_EQ(a.mClock, b.mClock);
ASSERT_EQ(a.mChannels, b.mChannels);
@ -365,7 +373,7 @@ class JsepTrackTest : public ::testing::Test
ASSERT_TRUE(!!a.GetNegotiatedDetails());
ASSERT_TRUE(!!b.GetNegotiatedDetails());
ASSERT_EQ(a.GetMediaType(), b.GetMediaType());
ASSERT_EQ(a.GetStreamId(), b.GetStreamId());
ASSERT_EQ(a.GetStreamIds(), b.GetStreamIds());
ASSERT_EQ(a.GetTrackId(), b.GetTrackId());
ASSERT_EQ(a.GetCNAME(), b.GetCNAME());
ASSERT_NE(a.GetDirection(), b.GetDirection());
@ -380,23 +388,20 @@ class JsepTrackTest : public ::testing::Test
void SanityCheck() const
{
if (mSendOff && mRecvAns) {
SanityCheckTracks(*mSendOff, *mRecvAns);
}
if (mRecvOff && mSendAns) {
SanityCheckTracks(*mRecvOff, *mSendAns);
}
SanityCheckTracks(mSendOff, mRecvAns);
SanityCheckTracks(mRecvOff, mSendAns);
}
protected:
RefPtr<JsepTrack> mSendOff;
RefPtr<JsepTrack> mRecvOff;
RefPtr<JsepTrack> mSendAns;
RefPtr<JsepTrack> mRecvAns;
JsepTrack mSendOff;
JsepTrack mRecvOff;
JsepTrack mSendAns;
JsepTrack mRecvAns;
PtrVector<JsepCodecDescription> mOffCodecs;
PtrVector<JsepCodecDescription> mAnsCodecs;
UniquePtr<Sdp> mOffer;
UniquePtr<Sdp> mAnswer;
SsrcGenerator mSsrcGenerator;
};
TEST_F(JsepTrackTest, CreateDestroy)
@ -445,20 +450,18 @@ TEST_F(JsepTrackTest, CheckForMismatchedAudioCodecAndVideoTrack)
// make codecs including telephone-event (an audio codec)
offerCodecs.values = MakeCodecs(false, false, true);
RefPtr<JsepTrack> videoTrack = new JsepTrack(SdpMediaSection::kVideo,
"stream_id",
"track_id",
sdp::kSend);
JsepTrack videoTrack(SdpMediaSection::kVideo, sdp::kSend);
videoTrack.UpdateTrackIds(std::vector<std::string>(1, "stream_id"), "track_id");
// populate codecs and then make sure we don't have any audio codecs
// in the video track
videoTrack->PopulateCodecs(offerCodecs.values);
videoTrack.PopulateCodecs(offerCodecs.values);
bool found = false;
videoTrack->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
videoTrack.ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
found = false;
videoTrack->ForEachCodec(CheckForCodecType(SdpMediaSection::kVideo, &found));
videoTrack.ForEachCodec(CheckForCodecType(SdpMediaSection::kVideo, &found));
ASSERT_TRUE(found); // for sanity, make sure we did find video codecs
}
@ -491,21 +494,16 @@ TEST_F(JsepTrackTest, CheckVideoTrackWithHackedDtmfSdp)
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_TRUE(mSendOff.get());
ASSERT_TRUE(mRecvOff.get());
ASSERT_TRUE(mSendAns.get());
ASSERT_TRUE(mRecvAns.get());
// make sure we still don't find any audio codecs in the video track after
// hacking the sdp
bool found = false;
mSendOff->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
mSendOff.ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
mRecvOff->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
mRecvOff.ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
mSendAns->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
mSendAns.ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
mRecvAns->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
mRecvAns.ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
}
@ -530,13 +528,13 @@ TEST_F(JsepTrackTest, AudioNegotiationOffererDtmf)
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:101"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns)));
ASSERT_EQ("1", track->mDefaultPt);
}
@ -561,13 +559,13 @@ TEST_F(JsepTrackTest, AudioNegotiationAnswererDtmf)
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:101"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns)));
ASSERT_EQ("1", track->mDefaultPt);
}
@ -592,22 +590,22 @@ TEST_F(JsepTrackTest, AudioNegotiationOffererAnswererDtmf)
ASSERT_NE(mAnswer->ToString().find("a=fmtp:101 0-15"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
}
@ -639,22 +637,22 @@ TEST_F(JsepTrackTest, AudioNegotiationDtmfOffererNoFmtpAnswererFmtp)
ASSERT_NE(mAnswer->ToString().find("a=fmtp:101 0-15"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
}
@ -686,22 +684,22 @@ TEST_F(JsepTrackTest, AudioNegotiationDtmfOffererFmtpAnswererNoFmtp)
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:101"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
}
@ -734,22 +732,22 @@ TEST_F(JsepTrackTest, AudioNegotiationDtmfOffererNoFmtpAnswererNoFmtp)
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:101"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2, 1)));
ASSERT_TRUE((track = GetAudioCodec(mRecvAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
}
@ -774,13 +772,13 @@ TEST_F(JsepTrackTest, VideoNegotationOffererFEC)
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:122"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff)));
ASSERT_TRUE((track = GetVideoCodec(mSendOff)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff)));
ASSERT_TRUE((track = GetVideoCodec(mRecvOff)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns)));
ASSERT_TRUE((track = GetVideoCodec(mSendAns)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns)));
ASSERT_TRUE((track = GetVideoCodec(mRecvAns)));
ASSERT_EQ("120", track->mDefaultPt);
}
@ -805,13 +803,13 @@ TEST_F(JsepTrackTest, VideoNegotationAnswererFEC)
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:122"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff)));
ASSERT_TRUE((track = GetVideoCodec(mSendOff)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff)));
ASSERT_TRUE((track = GetVideoCodec(mRecvOff)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns)));
ASSERT_TRUE((track = GetVideoCodec(mSendAns)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns)));
ASSERT_TRUE((track = GetVideoCodec(mRecvAns)));
ASSERT_EQ("120", track->mDefaultPt);
}
@ -836,13 +834,13 @@ TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFEC)
ASSERT_NE(mAnswer->ToString().find("a=fmtp:122 120/126/123"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff, 4)));
ASSERT_TRUE((track = GetVideoCodec(mSendOff, 4)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff, 4)));
ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 4)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns, 4)));
ASSERT_TRUE((track = GetVideoCodec(mSendAns, 4)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns, 4)));
ASSERT_TRUE((track = GetVideoCodec(mRecvAns, 4)));
ASSERT_EQ("120", track->mDefaultPt);
}
@ -867,13 +865,13 @@ TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFECPreferred)
ASSERT_NE(mAnswer->ToString().find("a=fmtp:122 120/126/123"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff, 4)));
ASSERT_TRUE((track = GetVideoCodec(mSendOff, 4)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff, 4)));
ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 4)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns, 4)));
ASSERT_TRUE((track = GetVideoCodec(mSendAns, 4)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns, 4)));
ASSERT_TRUE((track = GetVideoCodec(mRecvAns, 4)));
ASSERT_EQ("122", track->mDefaultPt);
}
@ -902,13 +900,13 @@ TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFECMismatch)
ASSERT_NE(mAnswer->ToString().find("a=fmtp:122 120/123"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff, 3)));
ASSERT_TRUE((track = GetVideoCodec(mSendOff, 3)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff, 3)));
ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 3)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns, 3)));
ASSERT_TRUE((track = GetVideoCodec(mSendAns, 3)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns, 3)));
ASSERT_TRUE((track = GetVideoCodec(mRecvAns, 3)));
ASSERT_EQ("122", track->mDefaultPt);
}
@ -964,11 +962,11 @@ TEST_F(JsepTrackTest, VideoNegotiationOfferRemb)
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
CheckOtherFbsSize(*mSendOff, 0);
CheckOtherFbsSize(*mRecvAns, 0);
CheckOtherFbsSize(mSendOff, 0);
CheckOtherFbsSize(mRecvAns, 0);
CheckOtherFbsSize(*mSendAns, 0);
CheckOtherFbsSize(*mRecvOff, 0);
CheckOtherFbsSize(mSendAns, 0);
CheckOtherFbsSize(mRecvOff, 0);
}
TEST_F(JsepTrackTest, VideoNegotiationAnswerRemb)
@ -988,11 +986,11 @@ TEST_F(JsepTrackTest, VideoNegotiationAnswerRemb)
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
CheckOtherFbsSize(*mSendOff, 0);
CheckOtherFbsSize(*mRecvAns, 0);
CheckOtherFbsSize(mSendOff, 0);
CheckOtherFbsSize(mRecvAns, 0);
CheckOtherFbsSize(*mSendAns, 0);
CheckOtherFbsSize(*mRecvOff, 0);
CheckOtherFbsSize(mSendAns, 0);
CheckOtherFbsSize(mRecvOff, 0);
}
TEST_F(JsepTrackTest, VideoNegotiationOfferAnswerRemb)
@ -1013,22 +1011,22 @@ TEST_F(JsepTrackTest, VideoNegotiationOfferAnswerRemb)
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
CheckOtherFbsSize(*mSendOff, 1);
CheckOtherFbsSize(*mRecvAns, 1);
CheckOtherFbExists(*mSendOff, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbExists(*mRecvAns, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbsSize(mSendOff, 1);
CheckOtherFbsSize(mRecvAns, 1);
CheckOtherFbExists(mSendOff, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbExists(mRecvAns, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbsSize(*mSendAns, 1);
CheckOtherFbsSize(*mRecvOff, 1);
CheckOtherFbExists(*mSendAns, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbExists(*mRecvOff, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbsSize(mSendAns, 1);
CheckOtherFbsSize(mRecvOff, 1);
CheckOtherFbExists(mSendAns, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbExists(mRecvOff, SdpRtcpFbAttributeList::kRemb);
}
TEST_F(JsepTrackTest, AudioOffSendonlyAnsRecvonly)
{
Init(SdpMediaSection::kAudio);
mRecvOff = nullptr;
mSendAns = nullptr;
GetOffer().SetDirection(SdpDirectionAttribute::kSendonly);
GetAnswer().SetDirection(SdpDirectionAttribute::kRecvonly);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(0);
@ -1037,8 +1035,8 @@ TEST_F(JsepTrackTest, AudioOffSendonlyAnsRecvonly)
TEST_F(JsepTrackTest, VideoOffSendonlyAnsRecvonly)
{
Init(SdpMediaSection::kVideo);
mRecvOff = nullptr;
mSendAns = nullptr;
GetOffer().SetDirection(SdpDirectionAttribute::kSendonly);
GetAnswer().SetDirection(SdpDirectionAttribute::kRecvonly);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(0);
@ -1047,7 +1045,7 @@ TEST_F(JsepTrackTest, VideoOffSendonlyAnsRecvonly)
TEST_F(JsepTrackTest, AudioOffSendrecvAnsRecvonly)
{
Init(SdpMediaSection::kAudio);
mSendAns = nullptr;
GetAnswer().SetDirection(SdpDirectionAttribute::kRecvonly);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(0);
@ -1056,25 +1054,27 @@ TEST_F(JsepTrackTest, AudioOffSendrecvAnsRecvonly)
TEST_F(JsepTrackTest, VideoOffSendrecvAnsRecvonly)
{
Init(SdpMediaSection::kVideo);
mSendAns = nullptr;
GetAnswer().SetDirection(SdpDirectionAttribute::kRecvonly);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(0);
}
TEST_F(JsepTrackTest, AudioOffRecvonlyAnsSendrecv)
TEST_F(JsepTrackTest, AudioOffRecvonlyAnsSendonly)
{
Init(SdpMediaSection::kAudio);
mSendOff = nullptr;
GetOffer().SetDirection(SdpDirectionAttribute::kRecvonly);
GetAnswer().SetDirection(SdpDirectionAttribute::kSendonly);
OfferAnswer();
CheckOffEncodingCount(0);
CheckAnsEncodingCount(1);
}
TEST_F(JsepTrackTest, VideoOffRecvonlyAnsSendrecv)
TEST_F(JsepTrackTest, VideoOffRecvonlyAnsSendonly)
{
Init(SdpMediaSection::kVideo);
mSendOff = nullptr;
GetOffer().SetDirection(SdpDirectionAttribute::kRecvonly);
GetAnswer().SetDirection(SdpDirectionAttribute::kSendonly);
OfferAnswer();
CheckOffEncodingCount(0);
CheckAnsEncodingCount(1);
@ -1083,7 +1083,7 @@ TEST_F(JsepTrackTest, VideoOffRecvonlyAnsSendrecv)
TEST_F(JsepTrackTest, AudioOffSendrecvAnsSendonly)
{
Init(SdpMediaSection::kAudio);
mRecvAns = nullptr;
GetAnswer().SetDirection(SdpDirectionAttribute::kSendonly);
OfferAnswer();
CheckOffEncodingCount(0);
CheckAnsEncodingCount(1);
@ -1092,7 +1092,7 @@ TEST_F(JsepTrackTest, AudioOffSendrecvAnsSendonly)
TEST_F(JsepTrackTest, VideoOffSendrecvAnsSendonly)
{
Init(SdpMediaSection::kVideo);
mRecvAns = nullptr;
GetAnswer().SetDirection(SdpDirectionAttribute::kSendonly);
OfferAnswer();
CheckOffEncodingCount(0);
CheckAnsEncodingCount(1);
@ -1161,7 +1161,7 @@ TEST_F(JsepTrackTest, DataChannelDraft21)
mOffer.reset(new SipccSdp(SdpOrigin("", 0, 0, sdp::kIPv4, "")));
mOffer->AddMediaSection(
SdpMediaSection::kApplication,
SdpDirectionAttribute::kInactive,
SdpDirectionAttribute::kSendrecv,
0,
SdpMediaSection::kUdpDtlsSctp,
sdp::kIPv4,
@ -1169,7 +1169,7 @@ TEST_F(JsepTrackTest, DataChannelDraft21)
mAnswer.reset(new SipccSdp(SdpOrigin("", 0, 0, sdp::kIPv4, "")));
mAnswer->AddMediaSection(
SdpMediaSection::kApplication,
SdpDirectionAttribute::kInactive,
SdpDirectionAttribute::kSendrecv,
0,
SdpMediaSection::kUdpDtlsSctp,
sdp::kIPv4,
@ -1202,7 +1202,7 @@ TEST_F(JsepTrackTest, SimulcastRejected)
std::vector<JsepTrack::JsConstraints> constraints;
constraints.push_back(MakeConstraints("foo", 40000));
constraints.push_back(MakeConstraints("bar", 10000));
mSendOff->SetJsConstraints(constraints);
mSendOff.SetJsConstraints(constraints);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
@ -1214,7 +1214,7 @@ TEST_F(JsepTrackTest, SimulcastPrevented)
std::vector<JsepTrack::JsConstraints> constraints;
constraints.push_back(MakeConstraints("foo", 40000));
constraints.push_back(MakeConstraints("bar", 10000));
mSendAns->SetJsConstraints(constraints);
mSendAns.SetJsConstraints(constraints);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
@ -1226,20 +1226,21 @@ TEST_F(JsepTrackTest, SimulcastOfferer)
std::vector<JsepTrack::JsConstraints> constraints;
constraints.push_back(MakeConstraints("foo", 40000));
constraints.push_back(MakeConstraints("bar", 10000));
mSendOff->SetJsConstraints(constraints);
mSendOff.SetJsConstraints(constraints);
CreateOffer();
CreateAnswer();
// Add simulcast/rid to answer
JsepTrack::AddToMsection(constraints, sdp::kRecv, &GetAnswer());
mRecvAns.AddToMsection(
constraints, sdp::kRecv, mSsrcGenerator, &GetAnswer());
Negotiate();
ASSERT_TRUE(mSendOff->GetNegotiatedDetails());
ASSERT_EQ(2U, mSendOff->GetNegotiatedDetails()->GetEncodingCount());
ASSERT_EQ("foo", mSendOff->GetNegotiatedDetails()->GetEncoding(0).mRid);
ASSERT_TRUE(mSendOff.GetNegotiatedDetails());
ASSERT_EQ(2U, mSendOff.GetNegotiatedDetails()->GetEncodingCount());
ASSERT_EQ("foo", mSendOff.GetNegotiatedDetails()->GetEncoding(0).mRid);
ASSERT_EQ(40000U,
mSendOff->GetNegotiatedDetails()->GetEncoding(0).mConstraints.maxBr);
ASSERT_EQ("bar", mSendOff->GetNegotiatedDetails()->GetEncoding(1).mRid);
mSendOff.GetNegotiatedDetails()->GetEncoding(0).mConstraints.maxBr);
ASSERT_EQ("bar", mSendOff.GetNegotiatedDetails()->GetEncoding(1).mRid);
ASSERT_EQ(10000U,
mSendOff->GetNegotiatedDetails()->GetEncoding(1).mConstraints.maxBr);
mSendOff.GetNegotiatedDetails()->GetEncoding(1).mConstraints.maxBr);
ASSERT_NE(std::string::npos,
mOffer->ToString().find("a=simulcast: send rid=foo;bar"));
ASSERT_NE(std::string::npos,
@ -1256,20 +1257,21 @@ TEST_F(JsepTrackTest, SimulcastAnswerer)
std::vector<JsepTrack::JsConstraints> constraints;
constraints.push_back(MakeConstraints("foo", 40000));
constraints.push_back(MakeConstraints("bar", 10000));
mSendAns->SetJsConstraints(constraints);
mSendAns.SetJsConstraints(constraints);
CreateOffer();
// Add simulcast/rid to offer
JsepTrack::AddToMsection(constraints, sdp::kRecv, &GetOffer());
mRecvOff.AddToMsection(
constraints, sdp::kRecv, mSsrcGenerator, &GetOffer());
CreateAnswer();
Negotiate();
ASSERT_TRUE(mSendAns->GetNegotiatedDetails());
ASSERT_EQ(2U, mSendAns->GetNegotiatedDetails()->GetEncodingCount());
ASSERT_EQ("foo", mSendAns->GetNegotiatedDetails()->GetEncoding(0).mRid);
ASSERT_TRUE(mSendAns.GetNegotiatedDetails());
ASSERT_EQ(2U, mSendAns.GetNegotiatedDetails()->GetEncodingCount());
ASSERT_EQ("foo", mSendAns.GetNegotiatedDetails()->GetEncoding(0).mRid);
ASSERT_EQ(40000U,
mSendAns->GetNegotiatedDetails()->GetEncoding(0).mConstraints.maxBr);
ASSERT_EQ("bar", mSendAns->GetNegotiatedDetails()->GetEncoding(1).mRid);
mSendAns.GetNegotiatedDetails()->GetEncoding(0).mConstraints.maxBr);
ASSERT_EQ("bar", mSendAns.GetNegotiatedDetails()->GetEncoding(1).mRid);
ASSERT_EQ(10000U,
mSendAns->GetNegotiatedDetails()->GetEncoding(1).mConstraints.maxBr);
mSendAns.GetNegotiatedDetails()->GetEncoding(1).mConstraints.maxBr);
ASSERT_NE(std::string::npos,
mOffer->ToString().find("a=simulcast: recv rid=foo;bar"));
ASSERT_NE(std::string::npos,
@ -1314,14 +1316,14 @@ TEST_F(JsepTrackTest, DefaultOpusParameters)
Init(SdpMediaSection::kAudio);
OfferAnswer();
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mSendOff,
VERIFY_OPUS_MAX_PLAYBACK_RATE(mSendOff,
SdpFmtpAttributeList::OpusParameters::kDefaultMaxPlaybackRate);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mSendAns,
VERIFY_OPUS_MAX_PLAYBACK_RATE(mSendAns,
SdpFmtpAttributeList::OpusParameters::kDefaultMaxPlaybackRate);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mRecvOff, 0U);
VERIFY_OPUS_FORCE_MONO(*mRecvOff, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mRecvAns, 0U);
VERIFY_OPUS_FORCE_MONO(*mRecvAns, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(mRecvOff, 0U);
VERIFY_OPUS_FORCE_MONO(mRecvOff, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(mRecvAns, 0U);
VERIFY_OPUS_FORCE_MONO(mRecvAns, false);
}
TEST_F(JsepTrackTest, NonDefaultOpusParameters)
@ -1339,15 +1341,15 @@ TEST_F(JsepTrackTest, NonDefaultOpusParameters)
InitSdp(SdpMediaSection::kAudio);
OfferAnswer();
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mSendOff, 16000U);
VERIFY_OPUS_FORCE_MONO(*mSendOff, true);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mSendAns,
VERIFY_OPUS_MAX_PLAYBACK_RATE(mSendOff, 16000U);
VERIFY_OPUS_FORCE_MONO(mSendOff, true);
VERIFY_OPUS_MAX_PLAYBACK_RATE(mSendAns,
SdpFmtpAttributeList::OpusParameters::kDefaultMaxPlaybackRate);
VERIFY_OPUS_FORCE_MONO(*mSendAns, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mRecvOff, 0U);
VERIFY_OPUS_FORCE_MONO(*mRecvOff, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mRecvAns, 16000U);
VERIFY_OPUS_FORCE_MONO(*mRecvAns, true);
VERIFY_OPUS_FORCE_MONO(mSendAns, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(mRecvOff, 0U);
VERIFY_OPUS_FORCE_MONO(mRecvOff, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(mRecvAns, 16000U);
VERIFY_OPUS_FORCE_MONO(mRecvAns, true);
}
} // namespace mozilla

Просмотреть файл

@ -15,13 +15,12 @@
#include "signaling/src/jsep/JsepTransport.h"
#include "signaling/src/sdp/Sdp.h"
#include "JsepTrack.h"
#include "signaling/src/jsep/JsepTransceiver.h"
namespace mozilla {
// Forward declarations
class JsepCodecDescription;
class JsepTrack;
enum JsepSignalingState {
kJsepStateStable,
@ -117,11 +116,9 @@ public:
void ForEachCodec(UnaryFunction& function)
{
std::for_each(Codecs().begin(), Codecs().end(), function);
for (RefPtr<JsepTrack>& track : GetLocalTracks()) {
track->ForEachCodec(function);
}
for (RefPtr<JsepTrack>& track : GetRemoteTracks()) {
track->ForEachCodec(function);
for (auto& transceiver : GetTransceivers()) {
transceiver->mSendTrack.ForEachCodec(function);
transceiver->mRecvTrack.ForEachCodec(function);
}
}
@ -129,45 +126,20 @@ public:
void SortCodecs(BinaryPredicate& sorter)
{
std::stable_sort(Codecs().begin(), Codecs().end(), sorter);
for (RefPtr<JsepTrack>& track : GetLocalTracks()) {
track->SortCodecs(sorter);
}
for (RefPtr<JsepTrack>& track : GetRemoteTracks()) {
track->SortCodecs(sorter);
for (auto& transceiver : GetTransceivers()) {
transceiver->mSendTrack.SortCodecs(sorter);
transceiver->mRecvTrack.SortCodecs(sorter);
}
}
// Manage tracks. We take shared ownership of any track.
virtual nsresult AddTrack(const RefPtr<JsepTrack>& track) = 0;
virtual nsresult RemoveTrack(const std::string& streamId,
const std::string& trackId) = 0;
virtual nsresult ReplaceTrack(const std::string& oldStreamId,
const std::string& oldTrackId,
const std::string& newStreamId,
const std::string& newTrackId) = 0;
virtual nsresult SetParameters(
const std::string& streamId,
const std::string& trackId,
const std::vector<JsepTrack::JsConstraints>& constraints) = 0;
// Helpful for firing events.
virtual std::vector<JsepTrack> GetRemoteTracksAdded() const = 0;
virtual std::vector<JsepTrack> GetRemoteTracksRemoved() const = 0;
virtual nsresult GetParameters(
const std::string& streamId,
const std::string& trackId,
std::vector<JsepTrack::JsConstraints>* outConstraints) = 0;
virtual std::vector<RefPtr<JsepTrack>> GetLocalTracks() const = 0;
virtual std::vector<RefPtr<JsepTrack>> GetRemoteTracks() const = 0;
virtual std::vector<RefPtr<JsepTrack>> GetRemoteTracksAdded() const = 0;
virtual std::vector<RefPtr<JsepTrack>> GetRemoteTracksRemoved() const = 0;
// Access the negotiated track pairs.
virtual std::vector<JsepTrackPair> GetNegotiatedTrackPairs() const = 0;
// Access transports.
virtual std::vector<RefPtr<JsepTransport>> GetTransports() const = 0;
virtual const std::vector<RefPtr<JsepTransceiver>>&
GetTransceivers() const = 0;
virtual std::vector<RefPtr<JsepTransceiver>>& GetTransceivers() = 0;
virtual nsresult AddTransceiver(RefPtr<JsepTransceiver> transceiver) = 0;
// Basic JSEP operations.
virtual nsresult CreateOffer(const JsepOfferOptions& options,
@ -218,29 +190,28 @@ public:
return states[state];
}
virtual bool AllLocalTracksAreAssigned() const = 0;
virtual bool CheckNegotiationNeeded() const = 0;
void
CountTracks(uint16_t (&receiving)[SdpMediaSection::kMediaTypes],
uint16_t (&sending)[SdpMediaSection::kMediaTypes]) const
{
auto trackPairs = GetNegotiatedTrackPairs();
memset(receiving, 0, sizeof(receiving));
memset(sending, 0, sizeof(sending));
for (auto& pair : trackPairs) {
if (pair.mReceiving) {
receiving[pair.mReceiving->GetMediaType()]++;
for (const auto& transceiver : GetTransceivers()) {
if (!transceiver->mRecvTrack.GetTrackId().empty()) {
receiving[transceiver->mRecvTrack.GetMediaType()]++;
}
if (pair.mSending) {
sending[pair.mSending->GetMediaType()]++;
if (!transceiver->mSendTrack.GetTrackId().empty()) {
sending[transceiver->mSendTrack.GetMediaType()]++;
}
}
}
protected:
const std::string mName;
JsepSignalingState mState;
uint32_t mNegotiations;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -10,9 +10,10 @@
#include <vector>
#include "signaling/src/jsep/JsepCodecDescription.h"
#include "signaling/src/jsep/JsepTrack.h"
#include "signaling/src/jsep/JsepSession.h"
#include "signaling/src/jsep/JsepTrack.h"
#include "signaling/src/jsep/JsepTransceiver.h"
#include "signaling/src/jsep/SsrcGenerator.h"
#include "signaling/src/sdp/SipccSdpParser.h"
#include "signaling/src/sdp/SdpHelper.h"
#include "signaling/src/common/PtrVector.h"
@ -48,11 +49,6 @@ public:
// Implement JsepSession methods.
virtual nsresult Init() override;
virtual nsresult AddTrack(const RefPtr<JsepTrack>& track) override;
virtual nsresult RemoveTrack(const std::string& streamId,
const std::string& trackId) override;
virtual nsresult SetIceCredentials(const std::string& ufrag,
const std::string& pwd) override;
virtual const std::string& GetUfrag() const override { return mIceUfrag; }
@ -99,30 +95,9 @@ public:
return mSupportedCodecs.values;
}
virtual nsresult ReplaceTrack(const std::string& oldStreamId,
const std::string& oldTrackId,
const std::string& newStreamId,
const std::string& newTrackId) override;
virtual std::vector<JsepTrack> GetRemoteTracksAdded() const override;
virtual nsresult SetParameters(
const std::string& streamId,
const std::string& trackId,
const std::vector<JsepTrack::JsConstraints>& constraints) override;
virtual nsresult GetParameters(
const std::string& streamId,
const std::string& trackId,
std::vector<JsepTrack::JsConstraints>* outConstraints) override;
virtual std::vector<RefPtr<JsepTrack>> GetLocalTracks() const override;
virtual std::vector<RefPtr<JsepTrack>> GetRemoteTracks() const override;
virtual std::vector<RefPtr<JsepTrack>>
GetRemoteTracksAdded() const override;
virtual std::vector<RefPtr<JsepTrack>>
GetRemoteTracksRemoved() const override;
virtual std::vector<JsepTrack> GetRemoteTracksRemoved() const override;
virtual nsresult CreateOffer(const JsepOfferOptions& options,
std::string* offer) override;
@ -176,20 +151,19 @@ public:
return mIsOfferer;
}
// Access transports.
virtual std::vector<RefPtr<JsepTransport>>
GetTransports() const override
{
return mTransports;
virtual const std::vector<RefPtr<JsepTransceiver>>&
GetTransceivers() const override {
return mTransceivers;
}
virtual std::vector<JsepTrackPair>
GetNegotiatedTrackPairs() const override
{
return mNegotiatedTrackPairs;
virtual std::vector<RefPtr<JsepTransceiver>>&
GetTransceivers() override {
return mTransceivers;
}
virtual bool AllLocalTracksAreAssigned() const override;
virtual nsresult AddTransceiver(RefPtr<JsepTransceiver> transceiver) override;
virtual bool CheckNegotiationNeeded() const override;
private:
struct JsepDtlsFingerprint {
@ -197,27 +171,16 @@ private:
std::vector<uint8_t> mValue;
};
struct JsepSendingTrack {
RefPtr<JsepTrack> mTrack;
Maybe<size_t> mAssignedMLine;
};
struct JsepReceivingTrack {
RefPtr<JsepTrack> mTrack;
Maybe<size_t> mAssignedMLine;
};
// Non-const so it can set mLastError
nsresult CreateGenericSDP(UniquePtr<Sdp>* sdp);
void AddExtmap(SdpMediaSection* msection) const;
void AddExtmap(SdpMediaSection* msection);
void AddMid(const std::string& mid, SdpMediaSection* msection) const;
const std::vector<SdpExtmapAttributeList::Extmap>* GetRtpExtensions(
SdpMediaSection::MediaType type) const;
std::vector<SdpExtmapAttributeList::Extmap> GetRtpExtensions(
const SdpMediaSection& msection);
void AddCommonExtmaps(const SdpMediaSection& remoteMsection,
SdpMediaSection* msection);
nsresult SetupIds();
nsresult CreateSsrc(uint32_t* ssrc);
void SetupDefaultCodecs();
void SetupDefaultRtpExtensions();
void SetState(JsepSignalingState state);
@ -231,12 +194,19 @@ private:
nsresult ValidateRemoteDescription(const Sdp& description);
nsresult ValidateOffer(const Sdp& offer);
nsresult ValidateAnswer(const Sdp& offer, const Sdp& answer);
nsresult SetRemoteTracksFromDescription(const Sdp* remoteDescription);
// Non-const because we use our Uuid generator
nsresult CreateReceivingTrack(size_t mline,
const Sdp& sdp,
const SdpMediaSection& msection,
RefPtr<JsepTrack>* track);
nsresult UpdateTransceiversFromRemoteDescription(const Sdp& remote);
bool WasMsectionDisabledLastNegotiation(size_t level) const;
JsepTransceiver* GetTransceiverForLevel(size_t level);
JsepTransceiver* GetTransceiverForLocal(size_t level);
JsepTransceiver* GetTransceiverForRemote(const SdpMediaSection& msection);
// The w3c and IETF specs have a lot of "magical" behavior that happens when
// addTrack is used. This was a deliberate design choice. Sadface.
JsepTransceiver* FindUnassociatedTransceiver(
SdpMediaSection::MediaType type, bool magic);
// Called for rollback of local description
void RollbackLocalOffer();
// Called for rollback of remote description
void RollbackRemoteOffer();
nsresult HandleNegotiatedSession(const UniquePtr<Sdp>& local,
const UniquePtr<Sdp>& remote);
nsresult AddTransportAttributes(SdpMediaSection* msection,
@ -245,53 +215,27 @@ private:
const Sdp& offerersPreviousSdp,
const Sdp& newOffer,
Sdp* newLocal);
nsresult SetupOfferMSections(const JsepOfferOptions& options, Sdp* sdp);
// Non-const so it can assign m-line index to tracks
nsresult SetupOfferMSectionsByType(SdpMediaSection::MediaType type,
const Maybe<size_t>& offerToReceive,
Sdp* sdp);
nsresult BindLocalTracks(SdpMediaSection::MediaType mediatype,
Sdp* sdp);
nsresult BindRemoteTracks(SdpMediaSection::MediaType mediatype,
Sdp* sdp,
size_t* offerToReceive);
nsresult SetRecvAsNeededOrDisable(SdpMediaSection::MediaType mediatype,
Sdp* sdp,
size_t* offerToRecv);
void SetupOfferToReceiveMsection(SdpMediaSection* offer);
nsresult AddRecvonlyMsections(SdpMediaSection::MediaType mediatype,
size_t count,
Sdp* sdp);
nsresult AddReofferMsections(const Sdp& oldLocalSdp,
const Sdp& oldAnswer,
Sdp* newSdp);
void CopyPreviousMsid(const Sdp& oldLocal, Sdp* newLocal);
void EnsureMsid(Sdp* remote);
void SetupBundle(Sdp* sdp) const;
nsresult GetRemoteIds(const Sdp& sdp,
const SdpMediaSection& msection,
std::string* streamId,
std::vector<std::string>* streamIds,
std::string* trackId);
nsresult CreateOfferMSection(SdpMediaSection::MediaType type,
SdpMediaSection::Protocol proto,
SdpDirectionAttribute::Direction direction,
Sdp* sdp);
nsresult GetFreeMsectionForSend(SdpMediaSection::MediaType type,
Sdp* sdp,
SdpMediaSection** msection);
nsresult CreateAnswerMSection(const JsepAnswerOptions& options,
size_t mlineIndex,
nsresult CreateOfferMsection(const JsepOfferOptions& options,
JsepTransceiver& transceiver,
Sdp* local);
nsresult CreateAnswerMsection(const JsepAnswerOptions& options,
JsepTransceiver& transceiver,
const SdpMediaSection& remoteMsection,
Sdp* sdp);
nsresult SetRecvonlySsrc(SdpMediaSection* msection);
nsresult BindMatchingLocalTrackToAnswer(SdpMediaSection* msection);
nsresult BindMatchingRemoteTrackToAnswer(SdpMediaSection* msection);
nsresult DetermineAnswererSetupRole(const SdpMediaSection& remoteMsection,
SdpSetupAttribute::Role* rolep);
nsresult MakeNegotiatedTrackPair(const SdpMediaSection& remote,
const SdpMediaSection& local,
const RefPtr<JsepTransport>& transport,
bool usingBundle,
size_t transportLevel,
JsepTrackPair* trackPairOut);
nsresult MakeNegotiatedTransceiver(const SdpMediaSection& remote,
const SdpMediaSection& local,
bool usingBundle,
size_t transportLevel,
JsepTransceiver* transceiverOut);
void InitTransport(const SdpMediaSection& msection, JsepTransport* transport);
nsresult FinalizeTransport(const SdpAttributeList& remote,
@ -308,15 +252,14 @@ private:
const;
const Sdp* GetAnswer() const;
std::vector<JsepSendingTrack> mLocalTracks;
std::vector<JsepReceivingTrack> mRemoteTracks;
// By the most recent SetRemoteDescription
std::vector<JsepReceivingTrack> mRemoteTracksAdded;
std::vector<JsepReceivingTrack> mRemoteTracksRemoved;
std::vector<RefPtr<JsepTransport> > mTransports;
// So we can rollback
std::vector<RefPtr<JsepTransport> > mOldTransports;
std::vector<JsepTrackPair> mNegotiatedTrackPairs;
std::vector<JsepTrack> mRemoteTracksAdded;
std::vector<JsepTrack> mRemoteTracksRemoved;
// !!!NOT INDEXED BY LEVEL!!! These are in the order they were created in. The
// level mapping is done with JsepTransceiver::mLevel.
std::vector<RefPtr<JsepTransceiver>> mTransceivers;
// So we can rollback. Not as simple as just going back to the old, though...
std::vector<RefPtr<JsepTransceiver>> mOldTransceivers;
bool mIsOfferer;
bool mWasOffererLastTime;
@ -335,14 +278,10 @@ private:
std::vector<SdpExtmapAttributeList::Extmap> mVideoRtpExtensions;
UniquePtr<JsepUuidGenerator> mUuidGen;
std::string mDefaultRemoteStreamId;
std::map<size_t, std::string> mDefaultRemoteTrackIdsByLevel;
std::string mCNAME;
// Used to prevent duplicate local SSRCs. Not used to prevent local/remote or
// remote-only duplication, which will be important for EKT but not now.
std::set<uint32_t> mSsrcs;
// When an m-section doesn't have a local track, it still needs an ssrc, which
// is stored here.
std::vector<uint32_t> mRecvonlySsrcs;
UniquePtr<Sdp> mGeneratedLocalDescription; // Created but not set.
UniquePtr<Sdp> mCurrentLocalDescription;
UniquePtr<Sdp> mCurrentRemoteDescription;
@ -352,6 +291,7 @@ private:
std::string mLastError;
SipccSdpParser mParser;
SdpHelper mSdpHelper;
SsrcGenerator mSsrcGenerator;
};
} // namespace mozilla

Просмотреть файл

@ -7,11 +7,12 @@
#include "signaling/src/jsep/JsepTrackEncoding.h"
#include <algorithm>
#include <iostream>
namespace mozilla
{
void
JsepTrack::GetNegotiatedPayloadTypes(std::vector<uint16_t>* payloadTypes)
JsepTrack::GetNegotiatedPayloadTypes(std::vector<uint16_t>* payloadTypes) const
{
if (!mNegotiatedDetails) {
return;
@ -88,6 +89,18 @@ JsepTrack::EnsureNoDuplicatePayloadTypes(
}
}
void
JsepTrack::EnsureSsrcs(SsrcGenerator& ssrcGenerator)
{
if (mSsrcs.empty()) {
uint32_t ssrc;
if (!ssrcGenerator.GenerateSsrc(&ssrc)) {
return;
}
mSsrcs.push_back(ssrc);
}
}
void
JsepTrack::PopulateCodecs(const std::vector<JsepCodecDescription*>& prototype)
{
@ -102,17 +115,23 @@ JsepTrack::PopulateCodecs(const std::vector<JsepCodecDescription*>& prototype)
}
void
JsepTrack::AddToOffer(SdpMediaSection* offer) const
JsepTrack::AddToOffer(SsrcGenerator& ssrcGenerator, SdpMediaSection* offer)
{
AddToMsection(mPrototypeCodecs.values, offer);
if (mDirection == sdp::kSend) {
AddToMsection(mJsEncodeConstraints, sdp::kSend, offer);
std::vector<JsConstraints> constraints;
if (offer->IsSending()) {
constraints = mJsEncodeConstraints;
}
AddToMsection(constraints, sdp::kSend, ssrcGenerator, offer);
}
}
void
JsepTrack::AddToAnswer(const SdpMediaSection& offer,
SdpMediaSection* answer) const
SsrcGenerator& ssrcGenerator,
SdpMediaSection* answer)
{
// We do not modify mPrototypeCodecs here, since we're only creating an
// answer. Once offer/answer concludes, we will update mPrototypeCodecs.
@ -126,17 +145,27 @@ JsepTrack::AddToAnswer(const SdpMediaSection& offer,
AddToMsection(codecs.values, answer);
if (mDirection == sdp::kSend) {
std::vector<JsConstraints> constraints(mJsEncodeConstraints);
std::vector<SdpRidAttributeList::Rid> rids;
GetRids(offer, sdp::kRecv, &rids);
NegotiateRids(rids, &constraints);
AddToMsection(constraints, sdp::kSend, answer);
std::vector<JsConstraints> constraints;
if (answer->IsSending()) {
constraints = mJsEncodeConstraints;
std::vector<SdpRidAttributeList::Rid> rids;
GetRids(offer, sdp::kRecv, &rids);
NegotiateRids(rids, &constraints);
}
AddToMsection(constraints, sdp::kSend, ssrcGenerator, answer);
}
}
void
JsepTrack::SetJsConstraints(
const std::vector<JsConstraints>& constraintsList)
{
mJsEncodeConstraints = constraintsList;
}
void
JsepTrack::AddToMsection(const std::vector<JsepCodecDescription*>& codecs,
SdpMediaSection* msection) const
SdpMediaSection* msection)
{
MOZ_ASSERT(msection->GetMediaType() == mType);
MOZ_ASSERT(!codecs.empty());
@ -145,14 +174,19 @@ JsepTrack::AddToMsection(const std::vector<JsepCodecDescription*>& codecs,
codec->AddToMediaSection(*msection);
}
if (mDirection == sdp::kSend) {
if (msection->GetMediaType() != SdpMediaSection::kApplication) {
msection->SetSsrcs(mSsrcs, mCNAME);
msection->AddMsid(mStreamId, mTrackId);
if ((mDirection == sdp::kSend) &&
(mType != SdpMediaSection::kApplication) &&
msection->IsSending()) {
if (mStreamIds.empty()) {
msection->AddMsid("-", mTrackId);
} else {
for (const std::string& streamId : mStreamIds) {
msection->AddMsid(streamId, mTrackId);
// TODO(bug 1402912) Interop hack; older Firefox barfs if there is more
// than one msid. Remove when safe.
break;
}
}
msection->SetSending(true);
} else {
msection->SetReceiving(true);
}
}
@ -173,10 +207,32 @@ JsepTrack::NegotiateRids(const std::vector<SdpRidAttributeList::Rid>& rids,
}
}
/* static */
void
JsepTrack::UpdateSsrcs(SsrcGenerator& ssrcGenerator, size_t encodings)
{
MOZ_ASSERT(mDirection == sdp::kSend);
MOZ_ASSERT(mType != SdpMediaSection::kApplication);
size_t numSsrcs = std::max<size_t>(encodings, 1U);
// Right now, the spec does not permit changing the number of encodings after
// the initial creation of the sender, so we don't need to worry about things
// like a new encoding inserted in between two pre-existing encodings.
while (mSsrcs.size() < numSsrcs) {
uint32_t ssrc;
if (!ssrcGenerator.GenerateSsrc(&ssrc)) {
return;
}
mSsrcs.push_back(ssrc);
}
mSsrcs.resize(numSsrcs);
MOZ_ASSERT(!mSsrcs.empty());
}
void
JsepTrack::AddToMsection(const std::vector<JsConstraints>& constraintsList,
sdp::Direction direction,
SsrcGenerator& ssrcGenerator,
SdpMediaSection* msection)
{
UniquePtr<SdpSimulcastAttribute> simulcast(new SdpSimulcastAttribute);
@ -198,10 +254,15 @@ JsepTrack::AddToMsection(const std::vector<JsConstraints>& constraintsList,
}
}
if (!rids->mRids.empty()) {
if (rids->mRids.size() > 1) {
msection->GetAttributeList().SetAttribute(simulcast.release());
msection->GetAttributeList().SetAttribute(rids.release());
}
if (mType != SdpMediaSection::kApplication && mDirection == sdp::kSend) {
UpdateSsrcs(ssrcGenerator, constraintsList.size());
msection->SetSsrcs(mSsrcs, mCNAME);
}
}
void
@ -281,6 +342,7 @@ JsepTrack::CreateEncodings(
max_streams = std::min(rids.size(), mJsEncodeConstraints.size());
}
// Drop SSRCs if less RIDs were offered than we have encoding constraints
// Just in case.
if (mSsrcs.size() > max_streams) {
mSsrcs.resize(max_streams);
}
@ -334,6 +396,7 @@ JsepTrack::NegotiateCodecs(
std::vector<JsepCodecDescription*>* codecs,
std::map<std::string, std::string>* formatChanges) const
{
MOZ_ASSERT(codecs->size());
PtrVector<JsepCodecDescription> unnegotiatedCodecs;
std::swap(unnegotiatedCodecs.values, *codecs);
@ -488,15 +551,6 @@ JsepTrack::Negotiate(const SdpMediaSection& answer,
}
}
if (mDirection == sdp::kRecv) {
mSsrcs.clear();
if (remote.GetAttributeList().HasAttribute(SdpAttribute::kSsrcAttribute)) {
for (auto& ssrcAttr : remote.GetAttributeList().GetSsrc().mSsrcs) {
AddSsrc(ssrcAttr.ssrc);
}
}
}
mNegotiatedDetails = Move(negotiatedDetails);
}
@ -506,13 +560,13 @@ JsepTrack::Negotiate(const SdpMediaSection& answer,
// We figure that out here.
/* static */
void
JsepTrack::SetUniquePayloadTypes(const std::vector<RefPtr<JsepTrack>>& tracks)
JsepTrack::SetUniquePayloadTypes(std::vector<JsepTrack*>& tracks)
{
// Maps to track details if no other track contains the payload type,
// otherwise maps to nullptr.
std::map<uint16_t, JsepTrackNegotiatedDetails*> payloadTypeToDetailsMap;
for (const RefPtr<JsepTrack>& track : tracks) {
for (JsepTrack* track : tracks) {
if (track->GetMediaType() == SdpMediaSection::kApplication) {
continue;
}

Просмотреть файл

@ -11,14 +11,11 @@
#include <map>
#include <set>
#include <mozilla/RefPtr.h>
#include <mozilla/UniquePtr.h>
#include <mozilla/Maybe.h>
#include "nsISupportsImpl.h"
#include "nsError.h"
#include "signaling/src/jsep/JsepTransport.h"
#include "signaling/src/jsep/JsepTrackEncoding.h"
#include "signaling/src/jsep/SsrcGenerator.h"
#include "signaling/src/sdp/Sdp.h"
#include "signaling/src/sdp/SdpAttribute.h"
#include "signaling/src/sdp/SdpMediaSection.h"
@ -33,6 +30,16 @@ public:
mTias(0)
{}
JsepTrackNegotiatedDetails(const JsepTrackNegotiatedDetails& orig) :
mExtmap(orig.mExtmap),
mUniquePayloadTypes(orig.mUniquePayloadTypes),
mTias(orig.mTias)
{
for (const JsepTrackEncoding* encoding : orig.mEncodings.values) {
mEncodings.values.push_back(new JsepTrackEncoding(*encoding));
}
}
size_t
GetEncodingCount() const
{
@ -88,15 +95,81 @@ class JsepTrack
{
public:
JsepTrack(mozilla::SdpMediaSection::MediaType type,
const std::string& streamid,
const std::string& trackid,
sdp::Direction direction = sdp::kSend)
sdp::Direction direction)
: mType(type),
mStreamId(streamid),
mTrackId(trackid),
mDirection(direction),
mActive(false)
{}
{
}
virtual ~JsepTrack() {}
void UpdateTrackIds(const std::vector<std::string>& streamIds,
const std::string& trackId)
{
mStreamIds = streamIds;
mTrackId = trackId;
}
void ClearTrackIds()
{
mStreamIds.clear();
mTrackId.clear();
}
void UpdateRecvTrack(const Sdp& sdp, const SdpMediaSection& msection)
{
MOZ_ASSERT(mDirection == sdp::kRecv);
MOZ_ASSERT(
msection.GetMediaType() != SdpMediaSection::MediaType::kApplication);
std::string error;
SdpHelper helper(&error);
if (msection.IsSending()) {
(void)helper.GetIdsFromMsid(sdp, msection, &mStreamIds, &mTrackId);
}
// We do this whether or not the track is active
SetCNAME(helper.GetCNAME(msection));
mSsrcs.clear();
if (msection.GetAttributeList().HasAttribute(
SdpAttribute::kSsrcAttribute)) {
for (auto& ssrcAttr : msection.GetAttributeList().GetSsrc().mSsrcs) {
mSsrcs.push_back(ssrcAttr.ssrc);
}
}
}
JsepTrack(const JsepTrack& orig)
{
*this = orig;
}
JsepTrack(JsepTrack&& orig) = default;
JsepTrack& operator=(JsepTrack&& rhs) = default;
JsepTrack& operator=(const JsepTrack& rhs)
{
if (this != &rhs) {
mType = rhs.mType;
mStreamIds = rhs.mStreamIds;
mTrackId = rhs.mTrackId;
mCNAME = rhs.mCNAME;
mDirection = rhs.mDirection;
mJsEncodeConstraints = rhs.mJsEncodeConstraints;
mSsrcs = rhs.mSsrcs;
mActive = rhs.mActive;
for (const JsepCodecDescription* codec : rhs.mPrototypeCodecs.values) {
mPrototypeCodecs.values.push_back(codec->Clone());
}
if (rhs.mNegotiatedDetails) {
mNegotiatedDetails.reset(
new JsepTrackNegotiatedDetails(*rhs.mNegotiatedDetails));
}
}
return *this;
}
virtual mozilla::SdpMediaSection::MediaType
GetMediaType() const
@ -104,16 +177,10 @@ public:
return mType;
}
virtual const std::string&
GetStreamId() const
virtual const std::vector<std::string>&
GetStreamIds() const
{
return mStreamId;
}
virtual void
SetStreamId(const std::string& id)
{
mStreamId = id;
return mStreamIds;
}
virtual const std::string&
@ -122,12 +189,6 @@ public:
return mTrackId;
}
virtual void
SetTrackId(const std::string& id)
{
mTrackId = id;
}
virtual const std::string&
GetCNAME() const
{
@ -152,13 +213,7 @@ public:
return mSsrcs;
}
virtual void
AddSsrc(uint32_t ssrc)
{
if (mType != SdpMediaSection::kApplication) {
mSsrcs.push_back(ssrc);
}
}
virtual void EnsureSsrcs(SsrcGenerator& ssrcGenerator);
bool
GetActive() const
@ -189,14 +244,18 @@ public:
mPrototypeCodecs.values.end(), sorter);
}
virtual void AddToOffer(SdpMediaSection* offer) const;
// These two are non-const because this is where ssrcs are chosen.
virtual void AddToOffer(SsrcGenerator& ssrcGenerator,
SdpMediaSection* offer);
virtual void AddToAnswer(const SdpMediaSection& offer,
SdpMediaSection* answer) const;
SsrcGenerator& ssrcGenerator,
SdpMediaSection* answer);
virtual void Negotiate(const SdpMediaSection& answer,
const SdpMediaSection& remote);
static void SetUniquePayloadTypes(
const std::vector<RefPtr<JsepTrack>>& tracks);
virtual void GetNegotiatedPayloadTypes(std::vector<uint16_t>* payloadTypes);
static void SetUniquePayloadTypes(std::vector<JsepTrack*>& tracks);
virtual void GetNegotiatedPayloadTypes(
std::vector<uint16_t>* payloadTypes) const;
// This will be set when negotiation is carried out.
virtual const JsepTrackNegotiatedDetails*
@ -223,18 +282,13 @@ public:
mNegotiatedDetails.reset();
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(JsepTrack);
struct JsConstraints
{
std::string rid;
EncodingConstraints constraints;
};
void SetJsConstraints(const std::vector<JsConstraints>& constraintsList)
{
mJsEncodeConstraints = constraintsList;
}
void SetJsConstraints(const std::vector<JsConstraints>& constraintsList);
void GetJsConstraints(std::vector<JsConstraints>* outConstraintsList) const
{
@ -242,12 +296,11 @@ public:
*outConstraintsList = mJsEncodeConstraints;
}
static void AddToMsection(const std::vector<JsConstraints>& constraintsList,
sdp::Direction direction,
SdpMediaSection* msection);
void AddToMsection(const std::vector<JsConstraints>& constraintsList,
sdp::Direction direction,
SsrcGenerator& ssrcGenerator,
SdpMediaSection* msection);
protected:
virtual ~JsepTrack() {}
private:
std::vector<JsepCodecDescription*> GetCodecClones() const;
@ -259,7 +312,7 @@ private:
static void EnsurePayloadTypeIsUnique(std::set<uint16_t>* uniquePayloadTypes,
JsepCodecDescription* codec);
void AddToMsection(const std::vector<JsepCodecDescription*>& codecs,
SdpMediaSection* msection) const;
SdpMediaSection* msection);
void GetRids(const SdpMediaSection& msection,
sdp::Direction direction,
std::vector<SdpRidAttributeList::Rid>* rids) const;
@ -281,12 +334,14 @@ private:
std::vector<JsConstraints>& constraintsList) const;
void NegotiateRids(const std::vector<SdpRidAttributeList::Rid>& rids,
std::vector<JsConstraints>* constraints) const;
void UpdateSsrcs(SsrcGenerator& ssrcGenerator, size_t encodings);
const mozilla::SdpMediaSection::MediaType mType;
std::string mStreamId;
mozilla::SdpMediaSection::MediaType mType;
// These are the ids that everyone outside of JsepSession care about
std::vector<std::string> mStreamIds;
std::string mTrackId;
std::string mCNAME;
const sdp::Direction mDirection;
sdp::Direction mDirection;
PtrVector<JsepCodecDescription> mPrototypeCodecs;
// Holds encoding params/constraints from JS. Simulcast happens when there are
// multiple of these. If there are none, we assume unconstrained unicast with
@ -297,32 +352,6 @@ private:
bool mActive;
};
// Need a better name for this.
struct JsepTrackPair {
size_t mLevel;
// Is this track pair sharing a transport with another?
size_t mBundleLevel = SIZE_MAX; // SIZE_MAX if no bundle level
uint32_t mRecvonlySsrc;
RefPtr<JsepTrack> mSending;
RefPtr<JsepTrack> mReceiving;
RefPtr<JsepTransport> mRtpTransport;
RefPtr<JsepTransport> mRtcpTransport;
bool HasBundleLevel() const {
return mBundleLevel != SIZE_MAX;
}
size_t BundleLevel() const {
MOZ_ASSERT(HasBundleLevel());
return mBundleLevel;
}
void SetBundleLevel(size_t aBundleLevel) {
MOZ_ASSERT(aBundleLevel != SIZE_MAX);
mBundleLevel = aBundleLevel;
}
};
} // namespace mozilla
#endif

Просмотреть файл

@ -19,6 +19,16 @@ namespace mozilla {
class JsepTrackEncoding
{
public:
JsepTrackEncoding() = default;
JsepTrackEncoding(const JsepTrackEncoding& orig) :
mConstraints(orig.mConstraints),
mRid(orig.mRid)
{
for (const JsepCodecDescription* codec : orig.mCodecs.values) {
mCodecs.values.push_back(codec->Clone());
}
}
const std::vector<JsepCodecDescription*>& GetCodecs() const
{
return mCodecs.values;

Просмотреть файл

@ -0,0 +1,235 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _JSEPTRANSCEIVER_H_
#define _JSEPTRANSCEIVER_H_
#include <string>
#include "signaling/src/sdp/SdpAttribute.h"
#include "signaling/src/sdp/SdpMediaSection.h"
#include "signaling/src/sdp/Sdp.h"
#include "signaling/src/jsep/JsepTransport.h"
#include "signaling/src/jsep/JsepTrack.h"
#include <mozilla/OwningNonNull.h>
#include "nsISupportsImpl.h"
#include "nsError.h"
namespace mozilla {
class JsepTransceiver {
private:
~JsepTransceiver() {};
public:
explicit JsepTransceiver(SdpMediaSection::MediaType type,
SdpDirectionAttribute::Direction jsDirection =
SdpDirectionAttribute::kSendrecv) :
mJsDirection(jsDirection),
mSendTrack(type, sdp::kSend),
mRecvTrack(type, sdp::kRecv),
mTransport(*(new JsepTransport)),
mLevel(SIZE_MAX),
mBundleLevel(SIZE_MAX),
mAddTrackMagic(false),
mWasCreatedBySetRemote(false),
mStopped(false),
mRemoved(false),
mNegotiated(false)
{}
// Can't use default copy c'tor because of the refcount members. Ugh.
JsepTransceiver(const JsepTransceiver& orig) :
mJsDirection(orig.mJsDirection),
mSendTrack(orig.mSendTrack),
mRecvTrack(orig.mRecvTrack),
mTransport(*(new JsepTransport(orig.mTransport))),
mMid(orig.mMid),
mLevel(orig.mLevel),
mBundleLevel(orig.mBundleLevel),
mAddTrackMagic(orig.mAddTrackMagic),
mWasCreatedBySetRemote(orig.mWasCreatedBySetRemote),
mStopped(orig.mStopped),
mRemoved(orig.mRemoved),
mNegotiated(orig.mNegotiated)
{}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(JsepTransceiver);
void Rollback(JsepTransceiver& oldTransceiver)
{
*mTransport = *oldTransceiver.mTransport;
mLevel = oldTransceiver.mLevel;
mBundleLevel = oldTransceiver.mBundleLevel;
mRecvTrack = oldTransceiver.mRecvTrack;
// stop() caused by a disabled m-section in a remote offer cannot be
// rolled back.
if (!IsStopped()) {
mMid = oldTransceiver.mMid;
}
}
bool IsAssociated() const
{
return !mMid.empty();
}
const std::string& GetMid() const
{
MOZ_ASSERT(IsAssociated());
return mMid;
}
void Associate(const std::string& mid)
{
MOZ_ASSERT(HasLevel());
mMid = mid;
}
void Disassociate()
{
mMid.clear();
}
bool HasLevel() const
{
return mLevel != SIZE_MAX;
}
void SetLevel(size_t level)
{
MOZ_ASSERT(level != SIZE_MAX);
MOZ_ASSERT(!HasLevel());
MOZ_ASSERT(!IsStopped());
mLevel = level;
}
void ClearLevel()
{
MOZ_ASSERT(mStopped);
MOZ_ASSERT(!IsAssociated());
mLevel = SIZE_MAX;
}
size_t GetLevel() const
{
MOZ_ASSERT(HasLevel());
return mLevel;
}
void Stop()
{
mStopped = true;
}
bool IsStopped() const
{
return mStopped;
}
void SetRemoved()
{
mRemoved = true;
}
bool IsRemoved() const
{
return mRemoved;
}
bool HasBundleLevel() const {
return mBundleLevel != SIZE_MAX;
}
size_t BundleLevel() const {
MOZ_ASSERT(HasBundleLevel());
return mBundleLevel;
}
void SetBundleLevel(size_t aBundleLevel) {
MOZ_ASSERT(aBundleLevel != SIZE_MAX);
mBundleLevel = aBundleLevel;
}
void ClearBundleLevel()
{
mBundleLevel = SIZE_MAX;
}
size_t GetTransportLevel() const
{
MOZ_ASSERT(HasLevel());
if (HasBundleLevel()) {
return BundleLevel();
}
return GetLevel();
}
void SetAddTrackMagic()
{
mAddTrackMagic = true;
}
bool HasAddTrackMagic() const
{
return mAddTrackMagic;
}
void SetCreatedBySetRemote()
{
mWasCreatedBySetRemote = true;
}
bool WasCreatedBySetRemote() const
{
return mWasCreatedBySetRemote;
}
void SetNegotiated()
{
MOZ_ASSERT(IsAssociated());
MOZ_ASSERT(HasLevel());
mNegotiated = true;
}
bool IsNegotiated() const
{
return mNegotiated;
}
// Convenience function
SdpMediaSection::MediaType GetMediaType() const
{
return mRecvTrack.GetMediaType();
}
// This is the direction JS wants. It might not actually happen.
SdpDirectionAttribute::Direction mJsDirection;
JsepTrack mSendTrack;
JsepTrack mRecvTrack;
OwningNonNull<JsepTransport> mTransport;
private:
// Stuff that is not negotiated
std::string mMid;
size_t mLevel; // SIZE_MAX if no level
// Is this track pair sharing a transport with another?
size_t mBundleLevel; // SIZE_MAX if no bundle level
// The w3c and IETF specs have a lot of "magical" behavior that happens
// when addTrack is used. This was a deliberate design choice. Sadface.
bool mAddTrackMagic;
bool mWasCreatedBySetRemote;
bool mStopped;
bool mRemoved;
bool mNegotiated;
};
} // namespace mozilla
#endif // _JSEPTRANSCEIVER_H_

Просмотреть файл

@ -87,6 +87,22 @@ public:
{
}
JsepTransport(const JsepTransport& orig)
{
*this = orig;
}
JsepTransport& operator=(const JsepTransport& orig)
{
if (this != &orig) {
mIce.reset(orig.mIce ? new JsepIceTransport(*orig.mIce) : nullptr);
mDtls.reset(orig.mDtls ? new JsepDtlsTransport(*orig.mDtls) : nullptr);
mTransportId = orig.mTransportId;
mComponents = orig.mComponents;
}
return *this;
}
void Close()
{
mComponents = 0;

Просмотреть файл

@ -0,0 +1,24 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "signaling/src/jsep/SsrcGenerator.h"
#include "pk11pub.h"
namespace mozilla {
bool
SsrcGenerator::GenerateSsrc(uint32_t* ssrc)
{
do {
SECStatus rv = PK11_GenerateRandom(
reinterpret_cast<unsigned char*>(ssrc), sizeof(uint32_t));
if (rv != SECSuccess) {
return false;
}
} while (mSsrcs.count(*ssrc));
mSsrcs.insert(*ssrc);
return true;
}
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _SSRCGENERATOR_H_
#define _SSRCGENERATOR_H_
#include <set>
namespace mozilla {
class SsrcGenerator {
public:
bool GenerateSsrc(uint32_t* ssrc);
private:
std::set<uint32_t> mSsrcs;
};
} // namespace mozilla
#endif // _SSRCGENERATOR_H_

Просмотреть файл

@ -13,7 +13,8 @@ LOCAL_INCLUDES += [
UNIFIED_SOURCES += [
'JsepSessionImpl.cpp',
'JsepTrack.cpp'
'JsepTrack.cpp',
'SsrcGenerator.cpp'
]
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -250,6 +250,22 @@ operator&(SdpDirectionAttribute::Direction d1,
return (SdpDirectionAttribute::Direction)((unsigned)d1 & (unsigned)d2);
}
inline SdpDirectionAttribute::Direction
operator|=(SdpDirectionAttribute::Direction& d1,
SdpDirectionAttribute::Direction d2)
{
d1 = d1 | d2;
return d1;
}
inline SdpDirectionAttribute::Direction
operator&=(SdpDirectionAttribute::Direction& d1,
SdpDirectionAttribute::Direction d2)
{
d1 = d1 & d2;
return d1;
}
///////////////////////////////////////////////////////////////////////////
// a=dtls-message, draft-rescorla-dtls-in-sdp
//-------------------------------------------------------------------------

Просмотреть файл

@ -453,9 +453,9 @@ SdpHelper::SetDefaultAddresses(const std::string& defaultCandidateAddr,
nsresult
SdpHelper::GetIdsFromMsid(const Sdp& sdp,
const SdpMediaSection& msection,
std::string* streamId,
std::string* trackId)
const SdpMediaSection& msection,
std::vector<std::string>* streamIds,
std::string* trackId)
{
if (!sdp.GetAttributeList().HasAttribute(
SdpAttribute::kMsidSemanticAttribute)) {
@ -493,13 +493,18 @@ SdpHelper::GetIdsFromMsid(const Sdp& sdp,
return NS_ERROR_INVALID_ARG;
}
if (!found) {
*streamId = i->identifier;
*trackId = i->appdata;
streamIds->clear();
found = true;
} else if ((*streamId != i->identifier) || (*trackId != i->appdata)) {
MOZ_MTLOG(ML_WARNING, "Found multiple different webrtc msids in "
"m-section " << msection.GetLevel() << ". The "
"behavior w/o transceivers is undefined.");
} else if ((*trackId != i->appdata)) {
SDP_SET_ERROR("Found multiple different webrtc track ids in m-section "
<< msection.GetLevel() << ". The behavior here is "
"undefined.");
return NS_ERROR_INVALID_ARG;
}
// "-" means no stream, see draft-ietf-mmusic-msid
if (i->identifier != "-") {
streamIds->push_back(i->identifier);
}
}
}

Просмотреть файл

@ -63,7 +63,7 @@ class SdpHelper {
std::string* mid);
nsresult GetIdsFromMsid(const Sdp& sdp,
const SdpMediaSection& msection,
std::string* streamId,
std::vector<std::string>* streamId,
std::string* trackId);
nsresult GetMsids(const SdpMediaSection& msection,
std::vector<SdpMsidAttributeList::Msid>* msids);

Просмотреть файл

@ -108,19 +108,19 @@ public:
inline bool
IsReceiving() const
{
return GetDirectionAttribute().mValue & sdp::kRecv;
return GetDirection() & sdp::kRecv;
}
inline bool
IsSending() const
{
return GetDirectionAttribute().mValue & sdp::kSend;
return GetDirection() & sdp::kSend;
}
inline void
SetReceiving(bool receiving)
{
auto direction = GetDirectionAttribute().mValue;
auto direction = GetDirection();
if (direction & sdp::kSend) {
SetDirection(receiving ?
SdpDirectionAttribute::kSendrecv :
@ -135,7 +135,7 @@ public:
inline void
SetSending(bool sending)
{
auto direction = GetDirectionAttribute().mValue;
auto direction = GetDirection();
if (direction & sdp::kRecv) {
SetDirection(sending ?
SdpDirectionAttribute::kSendrecv :
@ -152,6 +152,11 @@ public:
GetAttributeList().SetAttribute(new SdpDirectionAttribute(direction));
}
inline SdpDirectionAttribute::Direction GetDirection() const
{
return GetDirectionAttribute().mValue;
}
const SdpFmtpAttributeList::Parameters* FindFmtp(const std::string& pt) const;
void SetFmtp(const SdpFmtpAttributeList::Fmtp& fmtp);
void RemoveFmtp(const std::string& pt);