зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
cf90c6a366
Коммит
46f6fa03a6
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче