mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1160280: Put ssrc attributes in recvonly m-sections. r=ekr
This commit is contained in:
parent
1814e0f1e8
commit
521fa356e9
@ -111,16 +111,8 @@ JsepSessionImpl::AddTrack(const RefPtr<JsepTrack>& track)
|
||||
|
||||
if (track->GetSsrcs().empty()) {
|
||||
uint32_t ssrc;
|
||||
do {
|
||||
SECStatus rv = PK11_GenerateRandom(
|
||||
reinterpret_cast<unsigned char*>(&ssrc), sizeof(ssrc));
|
||||
if (rv != SECSuccess) {
|
||||
JSEP_SET_ERROR("Failed to generate SSRC, error=" << rv);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} while (mSsrcs.count(ssrc));
|
||||
|
||||
mSsrcs.insert(ssrc);
|
||||
nsresult rv = CreateSsrc(&ssrc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
track->AddSsrc(ssrc);
|
||||
}
|
||||
}
|
||||
@ -403,7 +395,7 @@ JsepSessionImpl::BindTrackToMsection(
|
||||
SdpMediaSection* msection)
|
||||
{
|
||||
if (msection->GetMediaType() != SdpMediaSection::kApplication) {
|
||||
AddLocalSsrcs(*track->mTrack, msection);
|
||||
SetSsrcs(track->mTrack->GetSsrcs(), msection);
|
||||
AddLocalIds(*track->mTrack, msection);
|
||||
}
|
||||
msection->SetSending(true);
|
||||
@ -841,21 +833,24 @@ JsepSessionImpl::AddMid(const std::string& mid,
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::AddLocalSsrcs(const JsepTrack& track,
|
||||
SdpMediaSection* msection) const
|
||||
JsepSessionImpl::SetSsrcs(const std::vector<uint32_t>& ssrcs,
|
||||
SdpMediaSection* msection) const
|
||||
{
|
||||
UniquePtr<SdpSsrcAttributeList> ssrcs(new SdpSsrcAttributeList);
|
||||
for (auto i = track.GetSsrcs().begin(); i != track.GetSsrcs().end(); ++i) {
|
||||
if (ssrcs.empty()) {
|
||||
msection->GetAttributeList().RemoveAttribute(SdpAttribute::kSsrcAttribute);
|
||||
return;
|
||||
}
|
||||
|
||||
UniquePtr<SdpSsrcAttributeList> ssrcAttr(new SdpSsrcAttributeList);
|
||||
for (auto ssrc : ssrcs) {
|
||||
// When using ssrc attributes, we are required to at least have a cname.
|
||||
// (See https://tools.ietf.org/html/rfc5576#section-6.1)
|
||||
std::string cnameAttr("cname:");
|
||||
cnameAttr += track.GetCNAME();
|
||||
ssrcs->PushEntry(*i, cnameAttr);
|
||||
cnameAttr += mCNAME;
|
||||
ssrcAttr->PushEntry(ssrc, cnameAttr);
|
||||
}
|
||||
|
||||
if (!ssrcs->mSsrcs.empty()) {
|
||||
msection->GetAttributeList().SetAttribute(ssrcs.release());
|
||||
}
|
||||
msection->GetAttributeList().SetAttribute(ssrcAttr.release());
|
||||
}
|
||||
|
||||
void
|
||||
@ -1024,15 +1019,7 @@ JsepSessionImpl::CreateAnswer(const JsepAnswerOptions& options,
|
||||
|
||||
for (size_t i = 0; i < numMsections; ++i) {
|
||||
const SdpMediaSection& remoteMsection = offer.GetMediaSection(i);
|
||||
SdpMediaSection& msection =
|
||||
sdp->AddMediaSection(remoteMsection.GetMediaType(),
|
||||
SdpDirectionAttribute::kInactive,
|
||||
9,
|
||||
remoteMsection.GetProtocol(),
|
||||
sdp::kIPv4,
|
||||
"0.0.0.0");
|
||||
|
||||
rv = CreateAnswerMSection(options, i, remoteMsection, &msection, sdp.get());
|
||||
rv = CreateAnswerMSection(options, i, remoteMsection, sdp.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -1101,7 +1088,7 @@ JsepSessionImpl::CreateOfferMSection(SdpMediaSection::MediaType mediatype,
|
||||
SdpMediaSection* msection =
|
||||
&sdp->AddMediaSection(mediatype, dir, 0, proto, sdp::kIPv4, "0.0.0.0");
|
||||
|
||||
return EnableMsection(msection);
|
||||
return EnableOfferMsection(msection);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1126,7 +1113,7 @@ JsepSessionImpl::GetFreeMsectionForSend(
|
||||
|
||||
if (MsectionIsDisabled(msection)) {
|
||||
// Was disabled; revive
|
||||
nsresult rv = EnableMsection(&msection);
|
||||
nsresult rv = EnableOfferMsection(&msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -1148,14 +1135,21 @@ nsresult
|
||||
JsepSessionImpl::CreateAnswerMSection(const JsepAnswerOptions& options,
|
||||
size_t mlineIndex,
|
||||
const SdpMediaSection& remoteMsection,
|
||||
SdpMediaSection* msection,
|
||||
Sdp* sdp)
|
||||
{
|
||||
nsresult rv = CopyStickyParams(remoteMsection, msection);
|
||||
SdpMediaSection& msection =
|
||||
sdp->AddMediaSection(remoteMsection.GetMediaType(),
|
||||
SdpDirectionAttribute::kInactive,
|
||||
9,
|
||||
remoteMsection.GetProtocol(),
|
||||
sdp::kIPv4,
|
||||
"0.0.0.0");
|
||||
|
||||
nsresult rv = CopyStickyParams(remoteMsection, &msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (MsectionIsDisabled(remoteMsection)) {
|
||||
DisableMsection(sdp, msection);
|
||||
DisableMsection(sdp, &msection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1163,18 +1157,21 @@ JsepSessionImpl::CreateAnswerMSection(const JsepAnswerOptions& options,
|
||||
rv = DetermineAnswererSetupRole(remoteMsection, &role);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AddTransportAttributes(msection, role);
|
||||
rv = AddTransportAttributes(&msection, role);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetRecvonlySsrc(&msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Only attempt to match up local tracks if the offerer has elected to
|
||||
// receive traffic.
|
||||
if (remoteMsection.IsReceiving()) {
|
||||
rv = BindMatchingLocalTrackForAnswer(msection);
|
||||
rv = BindMatchingLocalTrackForAnswer(&msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (remoteMsection.IsSending()) {
|
||||
msection->SetReceiving(true);
|
||||
msection.SetReceiving(true);
|
||||
}
|
||||
|
||||
// Now add the codecs.
|
||||
@ -1185,7 +1182,7 @@ JsepSessionImpl::CreateAnswerMSection(const JsepAnswerOptions& options,
|
||||
UniquePtr<JsepCodecDescription> negotiated(
|
||||
codec->MakeNegotiatedCodec(remoteMsection));
|
||||
if (negotiated) {
|
||||
negotiated->AddToMediaSection(*msection);
|
||||
negotiated->AddToMediaSection(msection);
|
||||
// TODO(bug 1099351): Once bug 1073475 is fixed on all supported
|
||||
// versions, we can remove this limitation.
|
||||
break;
|
||||
@ -1193,21 +1190,38 @@ JsepSessionImpl::CreateAnswerMSection(const JsepAnswerOptions& options,
|
||||
}
|
||||
|
||||
// Add extmap attributes.
|
||||
AddCommonExtmaps(remoteMsection, msection);
|
||||
AddCommonExtmaps(remoteMsection, &msection);
|
||||
|
||||
if (!msection->IsReceiving() && !msection->IsSending()) {
|
||||
DisableMsection(sdp, msection);
|
||||
if (!msection.IsReceiving() && !msection.IsSending()) {
|
||||
DisableMsection(sdp, &msection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (msection->GetFormats().empty()) {
|
||||
if (msection.GetFormats().empty()) {
|
||||
// Could not negotiate anything. Disable m-section.
|
||||
DisableMsection(sdp, msection);
|
||||
DisableMsection(sdp, &msection);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::SetRecvonlySsrc(SdpMediaSection* msection)
|
||||
{
|
||||
// If previous m-sections are disabled, we do not call this function for them
|
||||
while (mRecvonlySsrcs.size() <= msection->GetLevel()) {
|
||||
uint32_t ssrc;
|
||||
nsresult rv = CreateSsrc(&ssrc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mRecvonlySsrcs.push_back(ssrc);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> ssrcs;
|
||||
ssrcs.push_back(mRecvonlySsrcs[msection->GetLevel()]);
|
||||
SetSsrcs(ssrcs, msection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::BindMatchingLocalTrackForAnswer(SdpMediaSection* msection)
|
||||
{
|
||||
@ -1598,6 +1612,10 @@ JsepSessionImpl::MakeNegotiatedTrackPair(const SdpMediaSection& remote,
|
||||
|
||||
trackPairOut->mLevel = local.GetLevel();
|
||||
|
||||
MOZ_ASSERT(mRecvonlySsrcs.size() > local.GetLevel(),
|
||||
"Failed to set the default ssrc for an active m-section");
|
||||
trackPairOut->mRecvonlySsrc = mRecvonlySsrcs[local.GetLevel()];
|
||||
|
||||
if (usingBundle) {
|
||||
trackPairOut->mBundleLevel = Some(transportLevel);
|
||||
}
|
||||
@ -2363,6 +2381,22 @@ JsepSessionImpl::SetupIds()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::CreateSsrc(uint32_t* ssrc)
|
||||
{
|
||||
do {
|
||||
SECStatus rv = PK11_GenerateRandom(
|
||||
reinterpret_cast<unsigned char*>(ssrc), sizeof(uint32_t));
|
||||
if (rv != SECSuccess) {
|
||||
JSEP_SET_ERROR("Failed to generate SSRC, error=" << rv);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} while (mSsrcs.count(*ssrc));
|
||||
mSsrcs.insert(*ssrc);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::SetupDefaultCodecs()
|
||||
{
|
||||
@ -2836,7 +2870,7 @@ JsepSessionImpl::DisableMsection(Sdp* sdp, SdpMediaSection* msection) const
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::EnableMsection(SdpMediaSection* msection)
|
||||
JsepSessionImpl::EnableOfferMsection(SdpMediaSection* msection)
|
||||
{
|
||||
// We assert here because adding rtcp-mux to a non-disabled m-section that
|
||||
// did not already have rtcp-mux can cause problems.
|
||||
@ -2855,6 +2889,9 @@ JsepSessionImpl::EnableMsection(SdpMediaSection* msection)
|
||||
nsresult rv = AddTransportAttributes(msection, SdpSetupAttribute::kActpass);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetRecvonlySsrc(msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AddCodecs(msection);
|
||||
|
||||
AddExtmap(msection);
|
||||
|
@ -177,7 +177,8 @@ private:
|
||||
void AddCodecs(SdpMediaSection* msection) const;
|
||||
void AddExtmap(SdpMediaSection* msection) const;
|
||||
void AddMid(const std::string& mid, SdpMediaSection* msection) const;
|
||||
void AddLocalSsrcs(const JsepTrack& track, SdpMediaSection* msection) const;
|
||||
void SetSsrcs(const std::vector<uint32_t>& ssrcs,
|
||||
SdpMediaSection* msection) const;
|
||||
void AddLocalIds(const JsepTrack& track, SdpMediaSection* msection) const;
|
||||
JsepCodecDescription* FindMatchingCodec(
|
||||
const std::string& pt,
|
||||
@ -190,6 +191,7 @@ private:
|
||||
void AddCommonExtmaps(const SdpMediaSection& remoteMsection,
|
||||
SdpMediaSection* msection);
|
||||
nsresult SetupIds();
|
||||
nsresult CreateSsrc(uint32_t* ssrc);
|
||||
void SetupDefaultCodecs();
|
||||
void SetupDefaultRtpExtensions();
|
||||
void SetState(JsepSignalingState state);
|
||||
@ -262,8 +264,8 @@ private:
|
||||
nsresult CreateAnswerMSection(const JsepAnswerOptions& options,
|
||||
size_t mlineIndex,
|
||||
const SdpMediaSection& remoteMsection,
|
||||
SdpMediaSection* msection,
|
||||
Sdp* sdp);
|
||||
nsresult SetRecvonlySsrc(SdpMediaSection* msection);
|
||||
nsresult BindMatchingLocalTrackForAnswer(SdpMediaSection* msection);
|
||||
nsresult DetermineAnswererSetupRole(const SdpMediaSection& remoteMsection,
|
||||
SdpSetupAttribute::Role* rolep);
|
||||
@ -308,7 +310,7 @@ private:
|
||||
bool IsBundleSlave(const Sdp& localSdp, uint16_t level);
|
||||
|
||||
void DisableMsection(Sdp* sdp, SdpMediaSection* msection) const;
|
||||
nsresult EnableMsection(SdpMediaSection* msection);
|
||||
nsresult EnableOfferMsection(SdpMediaSection* msection);
|
||||
|
||||
nsresult SetUniquePayloadTypes();
|
||||
nsresult GetAllPayloadTypes(const JsepTrackNegotiatedDetails& trackDetails,
|
||||
@ -343,6 +345,9 @@ private:
|
||||
// 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;
|
||||
|
@ -162,6 +162,7 @@ struct JsepTrackPair {
|
||||
size_t mLevel;
|
||||
// Is this track pair sharing a transport with another?
|
||||
Maybe<size_t> mBundleLevel;
|
||||
uint32_t mRecvonlySsrc;
|
||||
RefPtr<JsepTrack> mSending;
|
||||
RefPtr<JsepTrack> mReceiving;
|
||||
RefPtr<JsepTransport> mRtpTransport;
|
||||
|
@ -112,7 +112,31 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
||||
|
||||
bool WebrtcAudioConduit::SetLocalSSRC(unsigned int ssrc)
|
||||
{
|
||||
return !mPtrRTP->SetLocalSSRC(mChannel, ssrc);
|
||||
unsigned int oldSsrc;
|
||||
if (!GetLocalSSRC(&oldSsrc)) {
|
||||
MOZ_ASSERT(false, "GetLocalSSRC failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (oldSsrc == ssrc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wasTransmitting = mEngineTransmitting;
|
||||
if (StopTransmitting() != kMediaConduitNoError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mPtrRTP->SetLocalSSRC(mChannel, ssrc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wasTransmitting) {
|
||||
if (StartTransmitting() != kMediaConduitNoError) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebrtcAudioConduit::GetLocalSSRC(unsigned int* ssrc) {
|
||||
|
@ -163,7 +163,31 @@ WebrtcVideoConduit::~WebrtcVideoConduit()
|
||||
|
||||
bool WebrtcVideoConduit::SetLocalSSRC(unsigned int ssrc)
|
||||
{
|
||||
return !mPtrRTP->SetLocalSSRC(mChannel, ssrc);
|
||||
unsigned int oldSsrc;
|
||||
if (!GetLocalSSRC(&oldSsrc)) {
|
||||
MOZ_ASSERT(false, "GetLocalSSRC failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (oldSsrc == ssrc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wasTransmitting = mEngineTransmitting;
|
||||
if (StopTransmitting() != kMediaConduitNoError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mPtrRTP->SetLocalSSRC(mChannel, ssrc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wasTransmitting) {
|
||||
if (StartTransmitting() != kMediaConduitNoError) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebrtcVideoConduit::GetLocalSSRC(unsigned int* ssrc)
|
||||
|
@ -365,6 +365,20 @@ MediaPipelineFactory::CreateOrUpdateMediaPipeline(
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<MediaSessionConduit> conduit;
|
||||
if (aTrack.GetMediaType() == SdpMediaSection::kAudio) {
|
||||
rv = GetOrCreateAudioConduit(aTrackPair, aTrack, &conduit);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
} else if (aTrack.GetMediaType() == SdpMediaSection::kVideo) {
|
||||
rv = GetOrCreateVideoConduit(aTrackPair, aTrack, &conduit);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
} else {
|
||||
// We've created the TransportFlow, nothing else to do here.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<MediaPipeline> pipeline =
|
||||
stream->GetPipelineByTrackId_m(aTrack.GetTrackId());
|
||||
|
||||
@ -391,20 +405,6 @@ MediaPipelineFactory::CreateOrUpdateMediaPipeline(
|
||||
<< " type=" << aTrack.GetMediaType()
|
||||
<< " direction=" << aTrack.GetDirection());
|
||||
|
||||
RefPtr<MediaSessionConduit> conduit;
|
||||
if (aTrack.GetMediaType() == SdpMediaSection::kAudio) {
|
||||
rv = GetOrCreateAudioConduit(aTrackPair, aTrack, &conduit);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
} else if (aTrack.GetMediaType() == SdpMediaSection::kVideo) {
|
||||
rv = GetOrCreateVideoConduit(aTrackPair, aTrack, &conduit);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
} else {
|
||||
// We've created the TransportFlow, nothing else to do here.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (receiving) {
|
||||
rv = CreateMediaPipelineReceiving(aTrackPair, aTrack,
|
||||
level, rtpFlow, rtcpFlow, filter,
|
||||
@ -619,6 +619,15 @@ MediaPipelineFactory::GetOrCreateAudioConduit(
|
||||
MOZ_MTLOG(ML_ERROR, "ConfigureRecvMediaCodecs failed: " << error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!aTrackPair.mSending) {
|
||||
// No send track, but we still need to configure an SSRC for receiver
|
||||
// reports.
|
||||
if (!conduit->SetLocalSSRC(aTrackPair.mRecvonlySsrc)) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For now we only expect to have one ssrc per local track.
|
||||
auto ssrcs = aTrack.GetSsrcs();
|
||||
@ -740,6 +749,15 @@ MediaPipelineFactory::GetOrCreateVideoConduit(
|
||||
MOZ_MTLOG(ML_ERROR, "ConfigureRecvMediaCodecs failed: " << error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!aTrackPair.mSending) {
|
||||
// No send track, but we still need to configure an SSRC for receiver
|
||||
// reports.
|
||||
if (!conduit->SetLocalSSRC(aTrackPair.mRecvonlySsrc)) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For now we only expect to have one ssrc per local track.
|
||||
auto ssrcs = aTrack.GetSsrcs();
|
||||
|
@ -2042,29 +2042,37 @@ TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines)
|
||||
std::string offer = CreateOffer(Some(options));
|
||||
|
||||
SipccSdpParser parser;
|
||||
auto outputSdp = parser.Parse(offer);
|
||||
ASSERT_TRUE(!!outputSdp) << "Should have valid SDP" << std::endl
|
||||
UniquePtr<Sdp> parsedOffer = parser.Parse(offer);
|
||||
ASSERT_TRUE(!!parsedOffer) << "Should have valid SDP" << std::endl
|
||||
<< "Errors were: " << GetParseErrors(parser);
|
||||
|
||||
ASSERT_EQ(3U, outputSdp->GetMediaSectionCount());
|
||||
ASSERT_EQ(3U, parsedOffer->GetMediaSectionCount());
|
||||
ASSERT_EQ(SdpMediaSection::kAudio,
|
||||
outputSdp->GetMediaSection(0).GetMediaType());
|
||||
parsedOffer->GetMediaSection(0).GetMediaType());
|
||||
ASSERT_EQ(SdpDirectionAttribute::kRecvonly,
|
||||
outputSdp->GetMediaSection(0).GetAttributeList().GetDirection());
|
||||
ASSERT_EQ(SdpMediaSection::kVideo,
|
||||
outputSdp->GetMediaSection(1).GetMediaType());
|
||||
ASSERT_EQ(SdpDirectionAttribute::kRecvonly,
|
||||
outputSdp->GetMediaSection(1).GetAttributeList().GetDirection());
|
||||
ASSERT_EQ(SdpMediaSection::kVideo,
|
||||
outputSdp->GetMediaSection(2).GetMediaType());
|
||||
ASSERT_EQ(SdpDirectionAttribute::kRecvonly,
|
||||
outputSdp->GetMediaSection(2).GetAttributeList().GetDirection());
|
||||
parsedOffer->GetMediaSection(0).GetAttributeList().GetDirection());
|
||||
ASSERT_TRUE(parsedOffer->GetMediaSection(0).GetAttributeList().HasAttribute(
|
||||
SdpAttribute::kSsrcAttribute));
|
||||
|
||||
ASSERT_TRUE(outputSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
|
||||
ASSERT_EQ(SdpMediaSection::kVideo,
|
||||
parsedOffer->GetMediaSection(1).GetMediaType());
|
||||
ASSERT_EQ(SdpDirectionAttribute::kRecvonly,
|
||||
parsedOffer->GetMediaSection(1).GetAttributeList().GetDirection());
|
||||
ASSERT_TRUE(parsedOffer->GetMediaSection(1).GetAttributeList().HasAttribute(
|
||||
SdpAttribute::kSsrcAttribute));
|
||||
|
||||
ASSERT_EQ(SdpMediaSection::kVideo,
|
||||
parsedOffer->GetMediaSection(2).GetMediaType());
|
||||
ASSERT_EQ(SdpDirectionAttribute::kRecvonly,
|
||||
parsedOffer->GetMediaSection(2).GetAttributeList().GetDirection());
|
||||
ASSERT_TRUE(parsedOffer->GetMediaSection(2).GetAttributeList().HasAttribute(
|
||||
SdpAttribute::kSsrcAttribute));
|
||||
|
||||
ASSERT_TRUE(parsedOffer->GetMediaSection(0).GetAttributeList().HasAttribute(
|
||||
SdpAttribute::kRtcpMuxAttribute));
|
||||
ASSERT_TRUE(outputSdp->GetMediaSection(1).GetAttributeList().HasAttribute(
|
||||
ASSERT_TRUE(parsedOffer->GetMediaSection(1).GetAttributeList().HasAttribute(
|
||||
SdpAttribute::kRtcpMuxAttribute));
|
||||
ASSERT_TRUE(outputSdp->GetMediaSection(2).GetAttributeList().HasAttribute(
|
||||
ASSERT_TRUE(parsedOffer->GetMediaSection(2).GetAttributeList().HasAttribute(
|
||||
SdpAttribute::kRtcpMuxAttribute));
|
||||
|
||||
SetLocalOffer(offer, CHECK_SUCCESS);
|
||||
@ -2073,21 +2081,33 @@ TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines)
|
||||
SetRemoteOffer(offer, CHECK_SUCCESS);
|
||||
|
||||
std::string answer = CreateAnswer();
|
||||
outputSdp = parser.Parse(answer);
|
||||
UniquePtr<Sdp> parsedAnswer = parser.Parse(answer);
|
||||
|
||||
ASSERT_EQ(3U, outputSdp->GetMediaSectionCount());
|
||||
ASSERT_EQ(3U, parsedAnswer->GetMediaSectionCount());
|
||||
ASSERT_EQ(SdpMediaSection::kAudio,
|
||||
outputSdp->GetMediaSection(0).GetMediaType());
|
||||
parsedAnswer->GetMediaSection(0).GetMediaType());
|
||||
ASSERT_EQ(SdpDirectionAttribute::kSendonly,
|
||||
outputSdp->GetMediaSection(0).GetAttributeList().GetDirection());
|
||||
parsedAnswer->GetMediaSection(0).GetAttributeList().GetDirection());
|
||||
ASSERT_EQ(SdpMediaSection::kVideo,
|
||||
outputSdp->GetMediaSection(1).GetMediaType());
|
||||
parsedAnswer->GetMediaSection(1).GetMediaType());
|
||||
ASSERT_EQ(SdpDirectionAttribute::kSendonly,
|
||||
outputSdp->GetMediaSection(1).GetAttributeList().GetDirection());
|
||||
parsedAnswer->GetMediaSection(1).GetAttributeList().GetDirection());
|
||||
ASSERT_EQ(SdpMediaSection::kVideo,
|
||||
outputSdp->GetMediaSection(2).GetMediaType());
|
||||
parsedAnswer->GetMediaSection(2).GetMediaType());
|
||||
ASSERT_EQ(SdpDirectionAttribute::kInactive,
|
||||
outputSdp->GetMediaSection(2).GetAttributeList().GetDirection());
|
||||
parsedAnswer->GetMediaSection(2).GetAttributeList().GetDirection());
|
||||
|
||||
SetLocalAnswer(answer, CHECK_SUCCESS);
|
||||
SetRemoteAnswer(answer, CHECK_SUCCESS);
|
||||
|
||||
std::vector<JsepTrackPair> trackPairs(mSessionOff.GetNegotiatedTrackPairs());
|
||||
ASSERT_EQ(2U, trackPairs.size());
|
||||
for (auto pair : trackPairs) {
|
||||
auto ssrcs = parsedOffer->GetMediaSection(pair.mLevel).GetAttributeList()
|
||||
.GetSsrc().mSsrcs;
|
||||
ASSERT_EQ(1U, ssrcs.size());
|
||||
ASSERT_EQ(pair.mRecvonlySsrc, ssrcs.front().ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(JsepSessionTest, OfferAnswerSendOnlyLines)
|
||||
|
Loading…
Reference in New Issue
Block a user