mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1203246 - Factor track negotiation stuff out of JsepSessionImpl, and other simplification. r=mt
This commit is contained in:
parent
6a05a4729d
commit
583bdbaf30
@ -159,6 +159,7 @@
|
||||
'./src/sdp/SdpHelper.h',
|
||||
'./src/sdp/SdpHelper.cpp',
|
||||
'./src/sdp/SdpMediaSection.h',
|
||||
'./src/sdp/SdpMediaSection.cpp',
|
||||
'./src/sdp/SipccSdp.h',
|
||||
'./src/sdp/SipccSdpAttributeList.h',
|
||||
'./src/sdp/SipccSdpAttributeList.cpp',
|
||||
@ -173,6 +174,7 @@
|
||||
'./src/jsep/JsepSession.h',
|
||||
'./src/jsep/JsepSessionImpl.cpp',
|
||||
'./src/jsep/JsepSessionImpl.h',
|
||||
'./src/jsep/JsepTrack.cpp',
|
||||
'./src/jsep/JsepTrack.h',
|
||||
'./src/jsep/JsepTransport.h'
|
||||
],
|
||||
|
@ -5,7 +5,6 @@
|
||||
#ifndef _JSEPCODECDESCRIPTION_H_
|
||||
#define _JSEPCODECDESCRIPTION_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "signaling/src/sdp/SdpMediaSection.h"
|
||||
#include "signaling/src/sdp/SdpHelper.h"
|
||||
@ -20,7 +19,8 @@ namespace mozilla {
|
||||
}
|
||||
|
||||
// A single entry in our list of known codecs.
|
||||
struct JsepCodecDescription {
|
||||
class JsepCodecDescription {
|
||||
public:
|
||||
JsepCodecDescription(mozilla::SdpMediaSection::MediaType type,
|
||||
const std::string& defaultPt,
|
||||
const std::string& name,
|
||||
@ -34,14 +34,12 @@ struct JsepCodecDescription {
|
||||
mChannels(channels),
|
||||
mEnabled(enabled),
|
||||
mStronglyPreferred(false),
|
||||
mNegotiated(false)
|
||||
mDirection(sdp::kSend)
|
||||
{
|
||||
}
|
||||
virtual ~JsepCodecDescription() {}
|
||||
|
||||
virtual JsepCodecDescription* Clone() const = 0;
|
||||
virtual void AddFmtps(SdpFmtpAttributeList& fmtp) const = 0;
|
||||
virtual void AddRtcpFbs(SdpRtcpFbAttributeList& rtcpfb) const = 0;
|
||||
|
||||
bool
|
||||
GetPtAsInt(uint16_t* ptOutparam) const
|
||||
@ -75,21 +73,9 @@ struct JsepCodecDescription {
|
||||
}
|
||||
|
||||
virtual bool
|
||||
Negotiate(const SdpMediaSection& remoteMsection)
|
||||
{
|
||||
mNegotiated = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool LoadSendParameters(
|
||||
const mozilla::SdpMediaSection& remoteMsection)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool LoadRecvParameters(
|
||||
const mozilla::SdpMediaSection& remoteMsection)
|
||||
Negotiate(const std::string& pt, const SdpMediaSection& remoteMsection)
|
||||
{
|
||||
mDefaultPt = pt;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -97,56 +83,21 @@ struct JsepCodecDescription {
|
||||
AddToMediaSection(SdpMediaSection& msection) const
|
||||
{
|
||||
if (mEnabled && msection.GetMediaType() == mType) {
|
||||
if (mType == SdpMediaSection::kApplication) {
|
||||
// Hack: using mChannels for number of streams
|
||||
msection.AddDataChannel(mDefaultPt, mName, mChannels);
|
||||
} else {
|
||||
msection.AddCodec(mDefaultPt, mName, mClock, mChannels);
|
||||
// Both send and recv codec will have the same pt, so don't add twice
|
||||
if (!msection.HasFormat(mDefaultPt)) {
|
||||
if (mType == SdpMediaSection::kApplication) {
|
||||
// Hack: using mChannels for number of streams
|
||||
msection.AddDataChannel(mDefaultPt, mName, mChannels);
|
||||
} else {
|
||||
msection.AddCodec(mDefaultPt, mName, mClock, mChannels);
|
||||
}
|
||||
}
|
||||
AddFmtpsToMSection(msection);
|
||||
AddRtcpFbsToMSection(msection);
|
||||
|
||||
AddParametersToMSection(msection);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddFmtpsToMSection(SdpMediaSection& msection) const
|
||||
{
|
||||
SdpAttributeList& attrs = msection.GetAttributeList();
|
||||
|
||||
UniquePtr<SdpFmtpAttributeList> fmtps;
|
||||
|
||||
if (attrs.HasAttribute(SdpAttribute::kFmtpAttribute)) {
|
||||
fmtps.reset(new SdpFmtpAttributeList(attrs.GetFmtp()));
|
||||
} else {
|
||||
fmtps.reset(new SdpFmtpAttributeList);
|
||||
}
|
||||
|
||||
AddFmtps(*fmtps);
|
||||
|
||||
if (!fmtps->mFmtps.empty()) {
|
||||
attrs.SetAttribute(fmtps.release());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddRtcpFbsToMSection(SdpMediaSection& msection) const
|
||||
{
|
||||
SdpAttributeList& attrs = msection.GetAttributeList();
|
||||
|
||||
UniquePtr<SdpRtcpFbAttributeList> rtcpfbs;
|
||||
|
||||
if (attrs.HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
|
||||
rtcpfbs.reset(new SdpRtcpFbAttributeList(attrs.GetRtcpFb()));
|
||||
} else {
|
||||
rtcpfbs.reset(new SdpRtcpFbAttributeList);
|
||||
}
|
||||
|
||||
AddRtcpFbs(*rtcpfbs);
|
||||
|
||||
if (!rtcpfbs->mFeedbacks.empty()) {
|
||||
attrs.SetAttribute(rtcpfbs.release());
|
||||
}
|
||||
}
|
||||
virtual void AddParametersToMSection(SdpMediaSection& msection) const {}
|
||||
|
||||
mozilla::SdpMediaSection::MediaType mType;
|
||||
std::string mDefaultPt;
|
||||
@ -155,10 +106,11 @@ struct JsepCodecDescription {
|
||||
uint32_t mChannels;
|
||||
bool mEnabled;
|
||||
bool mStronglyPreferred;
|
||||
bool mNegotiated;
|
||||
sdp::Direction mDirection;
|
||||
};
|
||||
|
||||
struct JsepAudioCodecDescription : public JsepCodecDescription {
|
||||
class JsepAudioCodecDescription : public JsepCodecDescription {
|
||||
public:
|
||||
JsepAudioCodecDescription(const std::string& defaultPt,
|
||||
const std::string& name,
|
||||
uint32_t clock,
|
||||
@ -173,25 +125,14 @@ struct JsepAudioCodecDescription : public JsepCodecDescription {
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddFmtps(SdpFmtpAttributeList& fmtp) const override
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddRtcpFbs(SdpRtcpFbAttributeList& rtcpfb) const override
|
||||
{
|
||||
// TODO: Do we want to add anything?
|
||||
}
|
||||
|
||||
JSEP_CODEC_CLONE(JsepAudioCodecDescription)
|
||||
|
||||
uint32_t mPacketSize;
|
||||
uint32_t mBitrate;
|
||||
};
|
||||
|
||||
struct JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
class JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
public:
|
||||
JsepVideoCodecDescription(const std::string& defaultPt,
|
||||
const std::string& name,
|
||||
uint32_t clock,
|
||||
@ -217,52 +158,83 @@ struct JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
mCcmFbTypes.push_back(SdpRtcpFbAttributeList::tmmbr);
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddFmtps(SdpFmtpAttributeList& fmtp) const override
|
||||
void
|
||||
AddParametersToMSection(SdpMediaSection& msection) const override
|
||||
{
|
||||
AddFmtpsToMSection(msection);
|
||||
AddRtcpFbsToMSection(msection);
|
||||
}
|
||||
|
||||
void
|
||||
AddFmtpsToMSection(SdpMediaSection& msection) const
|
||||
{
|
||||
if (mName == "H264") {
|
||||
UniquePtr<SdpFmtpAttributeList::H264Parameters> params =
|
||||
MakeUnique<SdpFmtpAttributeList::H264Parameters>();
|
||||
SdpFmtpAttributeList::H264Parameters h264Params(
|
||||
GetH264Parameters(mDefaultPt, msection));
|
||||
|
||||
params->packetization_mode = mPacketizationMode;
|
||||
if (mDirection == sdp::kSend) {
|
||||
if (!h264Params.level_asymmetry_allowed) {
|
||||
// First time the fmtp has been set; set just in case this is for a
|
||||
// sendonly m-line, since even though we aren't receiving the level
|
||||
// negotiation still needs to happen (sigh).
|
||||
h264Params.profile_level_id = mProfileLevelId;
|
||||
}
|
||||
} else {
|
||||
// Parameters that only apply to what we receive
|
||||
h264Params.max_mbps = mMaxMbps;
|
||||
h264Params.max_fs = mMaxFs;
|
||||
h264Params.max_cpb = mMaxCpb;
|
||||
h264Params.max_dpb = mMaxDpb;
|
||||
h264Params.max_br = mMaxBr;
|
||||
strncpy(h264Params.sprop_parameter_sets,
|
||||
mSpropParameterSets.c_str(),
|
||||
sizeof(h264Params.sprop_parameter_sets) - 1);
|
||||
h264Params.profile_level_id = mProfileLevelId;
|
||||
}
|
||||
|
||||
// Parameters that apply to both the send and recv directions
|
||||
h264Params.packetization_mode = mPacketizationMode;
|
||||
// Hard-coded, may need to change someday?
|
||||
params->level_asymmetry_allowed = true;
|
||||
params->profile_level_id = mProfileLevelId;
|
||||
params->max_mbps = mMaxMbps;
|
||||
params->max_fs = mMaxFs;
|
||||
params->max_cpb = mMaxCpb;
|
||||
params->max_dpb = mMaxDpb;
|
||||
params->max_br = mMaxBr;
|
||||
strncpy(params->sprop_parameter_sets,
|
||||
mSpropParameterSets.c_str(),
|
||||
sizeof(params->sprop_parameter_sets) - 1);
|
||||
fmtp.PushEntry(mDefaultPt, "", mozilla::Move(params));
|
||||
} else if (mName == "VP8" || mName == "VP9") {
|
||||
// VP8 and VP9 share the same SDP parameters thus far
|
||||
UniquePtr<SdpFmtpAttributeList::VP8Parameters> params =
|
||||
MakeUnique<SdpFmtpAttributeList::VP8Parameters>(
|
||||
mName == "VP8" ?
|
||||
SdpRtpmapAttributeList::kVP8 :
|
||||
SdpRtpmapAttributeList::kVP9);
|
||||
h264Params.level_asymmetry_allowed = true;
|
||||
|
||||
params->max_fs = mMaxFs;
|
||||
params->max_fr = mMaxFr;
|
||||
fmtp.PushEntry(mDefaultPt, "", mozilla::Move(params));
|
||||
msection.SetFmtp(
|
||||
SdpFmtpAttributeList::Fmtp(mDefaultPt, "", h264Params));
|
||||
} else if (mName == "VP8" || mName == "VP9") {
|
||||
if (mDirection == sdp::kRecv) {
|
||||
// VP8 and VP9 share the same SDP parameters thus far
|
||||
SdpFmtpAttributeList::VP8Parameters vp8Params(
|
||||
GetVP8Parameters(mDefaultPt, msection));
|
||||
|
||||
vp8Params.max_fs = mMaxFs;
|
||||
vp8Params.max_fr = mMaxFr;
|
||||
msection.SetFmtp(
|
||||
SdpFmtpAttributeList::Fmtp(mDefaultPt, "", vp8Params));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddRtcpFbs(SdpRtcpFbAttributeList& rtcpfb) const override
|
||||
void
|
||||
AddRtcpFbsToMSection(SdpMediaSection& msection) const
|
||||
{
|
||||
SdpRtcpFbAttributeList rtcpfbs(msection.GetRtcpFbs());
|
||||
for (const auto& rtcpfb : rtcpfbs.mFeedbacks) {
|
||||
if (rtcpfb.pt == mDefaultPt) {
|
||||
// Already set by the codec for the other direction.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& type : mAckFbTypes) {
|
||||
rtcpfb.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kAck, type);
|
||||
rtcpfbs.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kAck, type);
|
||||
}
|
||||
for (const std::string& type : mNackFbTypes) {
|
||||
rtcpfb.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kNack, type);
|
||||
rtcpfbs.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kNack, type);
|
||||
}
|
||||
for (const std::string& type : mCcmFbTypes) {
|
||||
rtcpfb.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kCcm, type);
|
||||
rtcpfbs.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kCcm, type);
|
||||
}
|
||||
|
||||
msection.SetRtcpFbs(rtcpfbs);
|
||||
}
|
||||
|
||||
SdpFmtpAttributeList::H264Parameters
|
||||
@ -326,22 +298,50 @@ struct JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
}
|
||||
|
||||
virtual bool
|
||||
Negotiate(const SdpMediaSection& remoteMsection) override
|
||||
Negotiate(const std::string& pt,
|
||||
const SdpMediaSection& remoteMsection) override
|
||||
{
|
||||
JsepCodecDescription::Negotiate(pt, remoteMsection);
|
||||
if (mName == "H264") {
|
||||
SdpFmtpAttributeList::H264Parameters h264Params(
|
||||
GetH264Parameters(mDefaultPt, remoteMsection));
|
||||
|
||||
// Level is negotiated symmetrically if level asymmetry is disallowed
|
||||
if (!h264Params.level_asymmetry_allowed) {
|
||||
SetSaneH264Level(std::min(GetSaneH264Level(h264Params.profile_level_id),
|
||||
GetSaneH264Level(mProfileLevelId)),
|
||||
&mProfileLevelId);
|
||||
}
|
||||
|
||||
// TODO(bug 1143709): max-recv-level support
|
||||
if (mDirection == sdp::kSend) {
|
||||
// Remote values of these apply only to the send codec.
|
||||
mMaxFs = h264Params.max_fs;
|
||||
mMaxMbps = h264Params.max_mbps;
|
||||
mMaxCpb = h264Params.max_cpb;
|
||||
mMaxDpb = h264Params.max_dpb;
|
||||
mMaxBr = h264Params.max_br;
|
||||
mSpropParameterSets = h264Params.sprop_parameter_sets;
|
||||
// Only do this if we didn't symmetrically negotiate above
|
||||
if (h264Params.level_asymmetry_allowed) {
|
||||
SetSaneH264Level(GetSaneH264Level(h264Params.profile_level_id),
|
||||
&mProfileLevelId);
|
||||
}
|
||||
} else {
|
||||
// TODO(bug 1143709): max-recv-level support
|
||||
}
|
||||
|
||||
} else if (mName == "VP8" || mName == "VP9") {
|
||||
if (mDirection == sdp::kSend) {
|
||||
SdpFmtpAttributeList::VP8Parameters vp8Params(
|
||||
GetVP8Parameters(mDefaultPt, remoteMsection));
|
||||
|
||||
mMaxFs = vp8Params.max_fs;
|
||||
mMaxFr = vp8Params.max_fr;
|
||||
}
|
||||
}
|
||||
|
||||
NegotiateRtcpFb(remoteMsection);
|
||||
return JsepCodecDescription::Negotiate(remoteMsection);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Maps the not-so-sane encoding of H264 level into something that is
|
||||
@ -396,47 +396,6 @@ struct JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
*profileLevelId = (*profileLevelId & ~levelMask) | level;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadSendParameters(const mozilla::SdpMediaSection& remoteMsection) override
|
||||
{
|
||||
|
||||
if (mName == "H264") {
|
||||
SdpFmtpAttributeList::H264Parameters h264Params(
|
||||
GetH264Parameters(mDefaultPt, remoteMsection));
|
||||
|
||||
if (!h264Params.level_asymmetry_allowed) {
|
||||
SetSaneH264Level(std::min(GetSaneH264Level(h264Params.profile_level_id),
|
||||
GetSaneH264Level(mProfileLevelId)),
|
||||
&mProfileLevelId);
|
||||
} else {
|
||||
SetSaneH264Level(GetSaneH264Level(h264Params.profile_level_id),
|
||||
&mProfileLevelId);
|
||||
}
|
||||
|
||||
mMaxFs = h264Params.max_fs;
|
||||
mMaxMbps = h264Params.max_mbps;
|
||||
mMaxCpb = h264Params.max_cpb;
|
||||
mMaxDpb = h264Params.max_dpb;
|
||||
mMaxBr = h264Params.max_br;
|
||||
mSpropParameterSets = h264Params.sprop_parameter_sets;
|
||||
} else if (mName == "VP8" || mName == "VP9") {
|
||||
SdpFmtpAttributeList::VP8Parameters vp8Params(
|
||||
GetVP8Parameters(mDefaultPt, remoteMsection));
|
||||
|
||||
mMaxFs = vp8Params.max_fs;
|
||||
mMaxFr = vp8Params.max_fr;
|
||||
}
|
||||
|
||||
NegotiateRtcpFb(remoteMsection);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadRecvParameters(const mozilla::SdpMediaSection& remoteMsection) override
|
||||
{
|
||||
return Negotiate(remoteMsection);
|
||||
}
|
||||
|
||||
enum Subprofile {
|
||||
kH264ConstrainedBaseline,
|
||||
kH264Baseline,
|
||||
@ -600,7 +559,8 @@ struct JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
std::string mSpropParameterSets;
|
||||
};
|
||||
|
||||
struct JsepApplicationCodecDescription : public JsepCodecDescription {
|
||||
class JsepApplicationCodecDescription : public JsepCodecDescription {
|
||||
public:
|
||||
JsepApplicationCodecDescription(const std::string& defaultPt,
|
||||
const std::string& name,
|
||||
uint16_t channels,
|
||||
@ -610,18 +570,6 @@ struct JsepApplicationCodecDescription : public JsepCodecDescription {
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddFmtps(SdpFmtpAttributeList& fmtp) const override
|
||||
{
|
||||
// TODO: Is there anything to do here?
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddRtcpFbs(SdpRtcpFbAttributeList& rtcpfb) const override
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
JSEP_CODEC_CLONE(JsepApplicationCodecDescription)
|
||||
|
||||
// Override, uses sctpmap instead of rtpmap
|
||||
|
@ -19,7 +19,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
// Forward declarations
|
||||
struct JsepCodecDescription;
|
||||
class JsepCodecDescription;
|
||||
class JsepTrack;
|
||||
struct JsepTrackPair;
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include "signaling/src/jsep/JsepTrack.h"
|
||||
#include "signaling/src/jsep/JsepTrack.h"
|
||||
#include "signaling/src/jsep/JsepTrackImpl.h"
|
||||
#include "signaling/src/jsep/JsepTransport.h"
|
||||
#include "signaling/src/sdp/Sdp.h"
|
||||
#include "signaling/src/sdp/SipccSdp.h"
|
||||
@ -38,15 +37,6 @@ MOZ_MTLOG_MODULE("jsep")
|
||||
MOZ_MTLOG(ML_ERROR, mLastError); \
|
||||
} while (0);
|
||||
|
||||
JsepSessionImpl::~JsepSessionImpl()
|
||||
{
|
||||
for (auto& codecs : mCodecsByLevel) {
|
||||
for (JsepCodecDescription* codec : codecs) {
|
||||
delete codec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::Init()
|
||||
{
|
||||
@ -113,7 +103,7 @@ nsresult
|
||||
JsepSessionImpl::AddTrack(const RefPtr<JsepTrack>& track)
|
||||
{
|
||||
mLastError.clear();
|
||||
MOZ_ASSERT(track->GetDirection() == JsepTrack::kJsepTrackSending);
|
||||
MOZ_ASSERT(track->GetDirection() == sdp::kSend);
|
||||
|
||||
if (track->GetMediaType() != SdpMediaSection::kApplication) {
|
||||
track->SetCNAME(mCNAME);
|
||||
@ -126,9 +116,10 @@ JsepSessionImpl::AddTrack(const RefPtr<JsepTrack>& track)
|
||||
}
|
||||
}
|
||||
|
||||
track->PopulateCodecs(mSupportedCodecs.values);
|
||||
|
||||
JsepSendingTrack strack;
|
||||
strack.mTrack = track;
|
||||
strack.mNegotiated = false;
|
||||
|
||||
mLocalTracks.push_back(strack);
|
||||
|
||||
@ -354,7 +345,7 @@ JsepSessionImpl::SetupOfferMSectionsByType(SdpMediaSection::MediaType mediatype,
|
||||
|
||||
// Make sure that m-sections that previously had a remote track have the
|
||||
// recv bit set. Only matters for renegotiation.
|
||||
rv = EnsureRecvForRemoteTracks(mediatype, sdp, offerToReceiveCountPtr);
|
||||
rv = BindRemoteTracks(mediatype, sdp, offerToReceiveCountPtr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If we need more recv sections, start setting the recv bit on other
|
||||
@ -374,65 +365,45 @@ JsepSessionImpl::SetupOfferMSectionsByType(SdpMediaSection::MediaType mediatype,
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::BindLocalTracks(SdpMediaSection::MediaType mediatype,
|
||||
Sdp* sdp)
|
||||
JsepSessionImpl::BindLocalTracks(SdpMediaSection::MediaType mediatype, Sdp* sdp)
|
||||
{
|
||||
for (auto track = mLocalTracks.begin(); track != mLocalTracks.end();
|
||||
++track) {
|
||||
if (mediatype != track->mTrack->GetMediaType()) {
|
||||
for (JsepSendingTrack& track : mLocalTracks) {
|
||||
if (mediatype != track.mTrack->GetMediaType()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SdpMediaSection* msection;
|
||||
|
||||
if (track->mAssignedMLine.isSome()) {
|
||||
// Renegotiation
|
||||
msection = &sdp->GetMediaSection(*track->mAssignedMLine);
|
||||
if (track.mAssignedMLine.isSome()) {
|
||||
msection = &sdp->GetMediaSection(*track.mAssignedMLine);
|
||||
} else {
|
||||
nsresult rv = GetFreeMsectionForSend(track->mTrack->GetMediaType(),
|
||||
nsresult rv = GetFreeMsectionForSend(track.mTrack->GetMediaType(),
|
||||
sdp,
|
||||
&msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
track.mAssignedMLine = Some(msection->GetLevel());
|
||||
}
|
||||
|
||||
nsresult rv = BindTrackToMsection(&(*track), msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
track.mTrack->AddToOffer(msection);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::BindTrackToMsection(
|
||||
JsepSendingTrack* track,
|
||||
SdpMediaSection* msection)
|
||||
JsepSessionImpl::BindRemoteTracks(SdpMediaSection::MediaType mediatype,
|
||||
Sdp* sdp,
|
||||
size_t* offerToReceive)
|
||||
{
|
||||
if (msection->GetMediaType() != SdpMediaSection::kApplication) {
|
||||
mSdpHelper.SetSsrcs(track->mTrack->GetSsrcs(), mCNAME, msection);
|
||||
AddLocalIds(*track->mTrack, msection);
|
||||
}
|
||||
msection->SetSending(true);
|
||||
track->mAssignedMLine = Some(msection->GetLevel());
|
||||
track->mNegotiated = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::EnsureRecvForRemoteTracks(SdpMediaSection::MediaType mediatype,
|
||||
Sdp* sdp,
|
||||
size_t* offerToReceive)
|
||||
{
|
||||
for (auto track = mRemoteTracks.begin(); track != mRemoteTracks.end();
|
||||
++track) {
|
||||
if (mediatype != track->mTrack->GetMediaType()) {
|
||||
for (JsepReceivingTrack& track : mRemoteTracks) {
|
||||
if (mediatype != track.mTrack->GetMediaType()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!track->mAssignedMLine.isSome()) {
|
||||
if (!track.mAssignedMLine.isSome()) {
|
||||
MOZ_ASSERT(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& msection = sdp->GetMediaSection(*track->mAssignedMLine);
|
||||
auto& msection = sdp->GetMediaSection(*track.mAssignedMLine);
|
||||
|
||||
if (mSdpHelper.MsectionIsDisabled(msection)) {
|
||||
// TODO(bug 1095226) Content probably disabled this? Should we allow
|
||||
@ -440,7 +411,8 @@ JsepSessionImpl::EnsureRecvForRemoteTracks(SdpMediaSection::MediaType mediatype,
|
||||
continue;
|
||||
}
|
||||
|
||||
msection.SetReceiving(true);
|
||||
track.mTrack->AddToOffer(&msection);
|
||||
|
||||
if (offerToReceive && *offerToReceive) {
|
||||
--(*offerToReceive);
|
||||
}
|
||||
@ -465,12 +437,12 @@ JsepSessionImpl::SetRecvAsNeededOrDisable(SdpMediaSection::MediaType mediatype,
|
||||
|
||||
if (offerToRecv) {
|
||||
if (*offerToRecv) {
|
||||
msection.SetReceiving(true);
|
||||
SetupOfferToReceiveMsection(&msection);
|
||||
--(*offerToRecv);
|
||||
continue;
|
||||
}
|
||||
} else if (msection.IsSending()) {
|
||||
msection.SetReceiving(true);
|
||||
SetupOfferToReceiveMsection(&msection);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -483,6 +455,18 @@ JsepSessionImpl::SetRecvAsNeededOrDisable(SdpMediaSection::MediaType mediatype,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::SetupOfferToReceiveMsection(SdpMediaSection* offer)
|
||||
{
|
||||
// Create a dummy recv track, and have it add codecs, set direction, etc.
|
||||
RefPtr<JsepTrack> dummy = new JsepTrack(offer->GetMediaType(),
|
||||
"",
|
||||
"",
|
||||
sdp::kRecv);
|
||||
dummy->PopulateCodecs(mSupportedCodecs.values);
|
||||
dummy->AddToOffer(offer);
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::AddRecvonlyMsections(SdpMediaSection::MediaType mediatype,
|
||||
size_t count,
|
||||
@ -496,6 +480,8 @@ JsepSessionImpl::AddRecvonlyMsections(SdpMediaSection::MediaType mediatype,
|
||||
sdp);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
SetupOfferToReceiveMsection(
|
||||
&sdp->GetMediaSection(sdp->GetMediaSectionCount() - 1));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -622,9 +608,9 @@ JsepSessionImpl::CreateOffer(const JsepOfferOptions& options,
|
||||
// Undo track assignments from a previous call to CreateOffer
|
||||
// (ie; if the track has not been negotiated yet, it doesn't necessarily need
|
||||
// to stay in the same m-section that it was in)
|
||||
for (auto i = mLocalTracks.begin(); i != mLocalTracks.end(); ++i) {
|
||||
if (!i->mNegotiated) {
|
||||
i->mAssignedMLine.reset();
|
||||
for (JsepSendingTrack& trackWrapper : mLocalTracks) {
|
||||
if (!trackWrapper.mTrack->GetNegotiatedDetails()) {
|
||||
trackWrapper.mAssignedMLine.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -683,128 +669,6 @@ JsepSessionImpl::GetRemoteDescription() const
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::AddCodecs(SdpMediaSection* msection) const
|
||||
{
|
||||
msection->ClearCodecs();
|
||||
for (const JsepCodecDescription* codec :
|
||||
mCodecsByLevel[msection->GetLevel()]) {
|
||||
codec->AddToMediaSection(*msection);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::PopulateCodecsByLevel(size_t numLevels)
|
||||
{
|
||||
while (mCodecsByLevel.size() < numLevels) {
|
||||
mCodecsByLevel.push_back(CreateCodecClones());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::UpdateCodecsForOffer(size_t level)
|
||||
{
|
||||
if (mCodecsByLevel.size() <= level) {
|
||||
// New m-section, populate with defaults
|
||||
PopulateCodecsByLevel(level + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
ResetNonNegotiatedCodecs(level);
|
||||
|
||||
EnsureNoDuplicatePayloadTypes(level);
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::ResetNonNegotiatedCodecs(size_t level)
|
||||
{
|
||||
for (size_t i = 0; i < mSupportedCodecs.values.size(); ++i) {
|
||||
if (mCodecsByLevel[level][i]->mNegotiated) {
|
||||
continue;
|
||||
}
|
||||
|
||||
delete mCodecsByLevel[level][i];
|
||||
mCodecsByLevel[level][i] = mSupportedCodecs.values[i]->Clone();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::GetNegotiatedPayloadTypes(size_t level,
|
||||
std::set<uint16_t>* types) const
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(level < mCodecsByLevel.size());
|
||||
MOZ_RELEASE_ASSERT(mCodecsByLevel[level].size() ==
|
||||
mSupportedCodecs.values.size());
|
||||
|
||||
for (size_t i = 0; i < mSupportedCodecs.values.size(); ++i) {
|
||||
if (!mCodecsByLevel[level][i]->mNegotiated) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t pt;
|
||||
if (!mCodecsByLevel[level][i]->GetPtAsInt(&pt)) {
|
||||
MOZ_ASSERT(false);
|
||||
continue;
|
||||
}
|
||||
MOZ_ASSERT(!types->count(pt));
|
||||
types->insert(pt);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::EnsureNoDuplicatePayloadTypes(size_t level)
|
||||
{
|
||||
std::set<uint16_t> payloadTypes;
|
||||
// Negotiated codecs need to keep their payload type. Codecs that were not
|
||||
// negotiated last time can use whatever is left.
|
||||
GetNegotiatedPayloadTypes(level, &payloadTypes);
|
||||
|
||||
for (JsepCodecDescription* codec : mCodecsByLevel[level]) {
|
||||
// We assume that no duplicates were negotiated.
|
||||
if (codec->mNegotiated || !codec->mEnabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disable, and only re-enable if we can ensure it has a unique pt.
|
||||
codec->mEnabled = false;
|
||||
|
||||
uint16_t currentPt;
|
||||
if (!codec->GetPtAsInt(¤tPt)) {
|
||||
MOZ_ASSERT(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!payloadTypes.count(currentPt)) {
|
||||
codec->mEnabled = true;
|
||||
payloadTypes.insert(currentPt);
|
||||
continue;
|
||||
}
|
||||
|
||||
// |codec| cannot use its current payload type. Try to find another.
|
||||
for (uint16_t freePt = 0; freePt <= 128; ++freePt) {
|
||||
// Not super efficient, but readability is probably more important.
|
||||
if (!payloadTypes.count(freePt)) {
|
||||
payloadTypes.insert(freePt);
|
||||
codec->mEnabled = true;
|
||||
std::ostringstream os;
|
||||
os << freePt;
|
||||
codec->mDefaultPt = os.str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<JsepCodecDescription*>
|
||||
JsepSessionImpl::CreateCodecClones() const
|
||||
{
|
||||
std::vector<JsepCodecDescription*> clones;
|
||||
for (const JsepCodecDescription* codec : mSupportedCodecs.values) {
|
||||
clones.push_back(codec->Clone());
|
||||
}
|
||||
return clones;
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::AddExtmap(SdpMediaSection* msection) const
|
||||
{
|
||||
@ -825,37 +689,6 @@ JsepSessionImpl::AddMid(const std::string& mid,
|
||||
SdpAttribute::kMidAttribute, mid));
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::AddLocalIds(const JsepTrack& track,
|
||||
SdpMediaSection* msection) const
|
||||
{
|
||||
if (track.GetMediaType() == SdpMediaSection::kApplication) {
|
||||
return;
|
||||
}
|
||||
|
||||
UniquePtr<SdpMsidAttributeList> msids(new SdpMsidAttributeList);
|
||||
if (msection->GetAttributeList().HasAttribute(SdpAttribute::kMsidAttribute)) {
|
||||
msids->mMsids = msection->GetAttributeList().GetMsid().mMsids;
|
||||
}
|
||||
|
||||
msids->PushEntry(track.GetStreamId(), track.GetTrackId());
|
||||
|
||||
msection->GetAttributeList().SetAttribute(msids.release());
|
||||
}
|
||||
|
||||
JsepCodecDescription*
|
||||
JsepSessionImpl::FindMatchingCodec(const std::string& fmt,
|
||||
const SdpMediaSection& msection) const
|
||||
{
|
||||
for (JsepCodecDescription* codec : mCodecsByLevel[msection.GetLevel()]) {
|
||||
if (codec->mEnabled && codec->Matches(fmt, msection)) {
|
||||
return codec;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::vector<SdpExtmapAttributeList::Extmap>*
|
||||
JsepSessionImpl::GetRtpExtensions(SdpMediaSection::MediaType type) const
|
||||
{
|
||||
@ -869,30 +702,6 @@ JsepSessionImpl::GetRtpExtensions(SdpMediaSection::MediaType type) const
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
CompareCodec(const JsepCodecDescription* lhs, const JsepCodecDescription* rhs)
|
||||
{
|
||||
return lhs->mStronglyPreferred && !rhs->mStronglyPreferred;
|
||||
}
|
||||
|
||||
std::vector<JsepCodecDescription*>
|
||||
JsepSessionImpl::GetCommonCodecs(const SdpMediaSection& offerMsection)
|
||||
{
|
||||
MOZ_ASSERT(!mIsOfferer);
|
||||
std::vector<JsepCodecDescription*> matchingCodecs;
|
||||
for (const std::string& fmt : offerMsection.GetFormats()) {
|
||||
JsepCodecDescription* codec = FindMatchingCodec(fmt, offerMsection);
|
||||
if (codec) {
|
||||
codec->mDefaultPt = fmt; // Remember the other side's PT
|
||||
matchingCodecs.push_back(codec);
|
||||
}
|
||||
}
|
||||
|
||||
std::stable_sort(matchingCodecs.begin(), matchingCodecs.end(), CompareCodec);
|
||||
|
||||
return matchingCodecs;
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::AddCommonExtmaps(const SdpMediaSection& remoteMsection,
|
||||
SdpMediaSection* msection)
|
||||
@ -940,26 +749,24 @@ JsepSessionImpl::CreateAnswer(const JsepAnswerOptions& options,
|
||||
|
||||
// Disable send for local tracks if the offer no longer allows it
|
||||
// (i.e., the m-section is recvonly, inactive or disabled)
|
||||
for (auto i = mLocalTracks.begin(); i != mLocalTracks.end(); ++i) {
|
||||
if (!i->mAssignedMLine.isSome()) {
|
||||
for (JsepSendingTrack& trackWrapper : mLocalTracks) {
|
||||
if (!trackWrapper.mAssignedMLine.isSome()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get rid of all m-line assignments that have not been negotiated
|
||||
if (!i->mNegotiated) {
|
||||
i->mAssignedMLine.reset();
|
||||
if (!trackWrapper.mTrack->GetNegotiatedDetails()) {
|
||||
trackWrapper.mAssignedMLine.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!offer.GetMediaSection(*i->mAssignedMLine).IsReceiving()) {
|
||||
i->mAssignedMLine.reset();
|
||||
if (!offer.GetMediaSection(*trackWrapper.mAssignedMLine).IsReceiving()) {
|
||||
trackWrapper.mAssignedMLine.reset();
|
||||
}
|
||||
}
|
||||
|
||||
size_t numMsections = offer.GetMediaSectionCount();
|
||||
|
||||
PopulateCodecsByLevel(numMsections);
|
||||
|
||||
for (size_t i = 0; i < numMsections; ++i) {
|
||||
const SdpMediaSection& remoteMsection = offer.GetMediaSection(i);
|
||||
rv = CreateAnswerMSection(options, i, remoteMsection, sdp.get());
|
||||
@ -1065,35 +872,22 @@ JsepSessionImpl::CreateAnswerMSection(const JsepAnswerOptions& options,
|
||||
// Only attempt to match up local tracks if the offerer has elected to
|
||||
// receive traffic.
|
||||
if (remoteMsection.IsReceiving()) {
|
||||
rv = BindMatchingLocalTrackForAnswer(&msection);
|
||||
rv = BindMatchingLocalTrackToAnswer(&msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (remoteMsection.IsSending()) {
|
||||
msection.SetReceiving(true);
|
||||
BindMatchingRemoteTrackToAnswer(&msection);
|
||||
}
|
||||
|
||||
// Now add the codecs.
|
||||
std::vector<JsepCodecDescription*> matchingCodecs(
|
||||
GetCommonCodecs(remoteMsection));
|
||||
|
||||
for (JsepCodecDescription* codec : matchingCodecs) {
|
||||
if (codec->Negotiate(remoteMsection)) {
|
||||
codec->AddToMediaSection(msection);
|
||||
// TODO(bug 1099351): Once bug 1073475 is fixed on all supported
|
||||
// versions, we can remove this limitation.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add extmap attributes.
|
||||
AddCommonExtmaps(remoteMsection, &msection);
|
||||
|
||||
if (!msection.IsReceiving() && !msection.IsSending()) {
|
||||
mSdpHelper.DisableMsection(sdp, &msection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Add extmap attributes.
|
||||
AddCommonExtmaps(remoteMsection, &msection);
|
||||
|
||||
if (msection.GetFormats().empty()) {
|
||||
// Could not negotiate anything. Disable m-section.
|
||||
mSdpHelper.DisableMsection(sdp, &msection);
|
||||
@ -1115,12 +909,12 @@ JsepSessionImpl::SetRecvonlySsrc(SdpMediaSection* msection)
|
||||
|
||||
std::vector<uint32_t> ssrcs;
|
||||
ssrcs.push_back(mRecvonlySsrcs[msection->GetLevel()]);
|
||||
mSdpHelper.SetSsrcs(ssrcs, mCNAME, msection);
|
||||
msection->SetSsrcs(ssrcs, mCNAME);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::BindMatchingLocalTrackForAnswer(SdpMediaSection* msection)
|
||||
JsepSessionImpl::BindMatchingLocalTrackToAnswer(SdpMediaSection* msection)
|
||||
{
|
||||
auto track = FindTrackByLevel(mLocalTracks, msection->GetLevel());
|
||||
|
||||
@ -1147,13 +941,31 @@ JsepSessionImpl::BindMatchingLocalTrackForAnswer(SdpMediaSection* msection)
|
||||
}
|
||||
|
||||
if (track != mLocalTracks.end()) {
|
||||
nsresult rv = BindTrackToMsection(&(*track), msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
track->mAssignedMLine = Some(msection->GetLevel());
|
||||
track->mTrack->AddToAnswer(
|
||||
mPendingRemoteDescription->GetMediaSection(msection->GetLevel()),
|
||||
msection);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::BindMatchingRemoteTrackToAnswer(SdpMediaSection* msection)
|
||||
{
|
||||
auto it = FindTrackByLevel(mRemoteTracks, msection->GetLevel());
|
||||
if (it == mRemoteTracks.end()) {
|
||||
MOZ_ASSERT(false);
|
||||
JSEP_SET_ERROR("Failed to find remote track for local answer m-section");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
it->mTrack->AddToAnswer(
|
||||
mPendingRemoteDescription->GetMediaSection(msection->GetLevel()),
|
||||
msection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::DetermineAnswererSetupRole(
|
||||
const SdpMediaSection& remoteMsection,
|
||||
@ -1408,14 +1220,22 @@ JsepSessionImpl::HandleNegotiatedSession(const UniquePtr<Sdp>& local,
|
||||
nsresult rv = mSdpHelper.GetBundledMids(answer, &bundledMids);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
std::vector<JsepTrackPair> trackPairs;
|
||||
|
||||
if (mTransports.size() < local->GetMediaSectionCount()) {
|
||||
JSEP_SET_ERROR("Fewer transports set up than m-lines");
|
||||
MOZ_ASSERT(false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
for (JsepSendingTrack& trackWrapper : mLocalTracks) {
|
||||
trackWrapper.mTrack->ClearNegotiatedDetails();
|
||||
}
|
||||
|
||||
for (JsepReceivingTrack& trackWrapper : mRemoteTracks) {
|
||||
trackWrapper.mTrack->ClearNegotiatedDetails();
|
||||
}
|
||||
|
||||
std::vector<JsepTrackPair> trackPairs;
|
||||
|
||||
// Now walk through the m-sections, make sure they match, and create
|
||||
// track pairs that describe the media to be set up.
|
||||
for (size_t i = 0; i < local->GetMediaSectionCount(); ++i) {
|
||||
@ -1472,20 +1292,12 @@ JsepSessionImpl::HandleNegotiatedSession(const UniquePtr<Sdp>& local,
|
||||
trackPairs.push_back(trackPair);
|
||||
}
|
||||
|
||||
rv = SetUniquePayloadTypes();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
JsepTrack::SetUniquePayloadTypes(GetTracks(mRemoteTracks));
|
||||
|
||||
// Ouch, this probably needs some dirty bit instead of just clearing
|
||||
// stuff for renegotiation.
|
||||
mNegotiatedTrackPairs = trackPairs;
|
||||
|
||||
// Mark all assigned local tracks as negotiated
|
||||
for (auto i = mLocalTracks.begin(); i != mLocalTracks.end(); ++i) {
|
||||
if (i->mAssignedMLine.isSome()) {
|
||||
i->mNegotiated = true;
|
||||
}
|
||||
}
|
||||
|
||||
mGeneratedLocalDescription.reset();
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1538,11 +1350,7 @@ JsepSessionImpl::MakeNegotiatedTrackPair(const SdpMediaSection& remote,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = NegotiateTrack(remote,
|
||||
local,
|
||||
JsepTrack::kJsepTrackSending,
|
||||
&sendTrack->mTrack);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
sendTrack->mTrack->Negotiate(answer, remote);
|
||||
|
||||
trackPairOut->mSending = sendTrack->mTrack;
|
||||
}
|
||||
@ -1557,18 +1365,7 @@ JsepSessionImpl::MakeNegotiatedTrackPair(const SdpMediaSection& remote,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = NegotiateTrack(remote,
|
||||
local,
|
||||
JsepTrack::kJsepTrackReceiving,
|
||||
&recvTrack->mTrack);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (remote.GetAttributeList().HasAttribute(SdpAttribute::kSsrcAttribute)) {
|
||||
auto& ssrcs = remote.GetAttributeList().GetSsrc().mSsrcs;
|
||||
for (auto i = ssrcs.begin(); i != ssrcs.end(); ++i) {
|
||||
recvTrack->mTrack->AddSsrc(i->ssrc);
|
||||
}
|
||||
}
|
||||
recvTrack->mTrack->Negotiate(answer, remote);
|
||||
|
||||
if (trackPairOut->mBundleLevel.isSome() &&
|
||||
recvTrack->mTrack->GetSsrcs().empty() &&
|
||||
@ -1592,87 +1389,6 @@ JsepSessionImpl::MakeNegotiatedTrackPair(const SdpMediaSection& remote,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::NegotiateTrack(const SdpMediaSection& remoteMsection,
|
||||
const SdpMediaSection& localMsection,
|
||||
JsepTrack::Direction direction,
|
||||
RefPtr<JsepTrack>* track)
|
||||
{
|
||||
UniquePtr<JsepTrackNegotiatedDetailsImpl> negotiatedDetails =
|
||||
MakeUnique<JsepTrackNegotiatedDetailsImpl>();
|
||||
negotiatedDetails->mProtocol = remoteMsection.GetProtocol();
|
||||
|
||||
auto& answerMsection = mIsOfferer ? remoteMsection : localMsection;
|
||||
|
||||
for (auto& format : answerMsection.GetFormats()) {
|
||||
JsepCodecDescription* origCodec = FindMatchingCodec(format, answerMsection);
|
||||
if (!origCodec) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure codec->mDefaultPt is consistent with what is in the remote
|
||||
// msection, since the following logic needs to look stuff up there.
|
||||
for (auto& remoteFormat : remoteMsection.GetFormats()) {
|
||||
if (origCodec->Matches(remoteFormat, remoteMsection)) {
|
||||
origCodec->mDefaultPt = remoteFormat;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UniquePtr<JsepCodecDescription> codec(origCodec->Clone());
|
||||
|
||||
bool sending = (direction == JsepTrack::kJsepTrackSending);
|
||||
|
||||
// Everywhere else in JsepSessionImpl, a JsepCodecDescription describes
|
||||
// what one side puts in its SDP. However, we don't want that here; we want
|
||||
// a JsepCodecDescription that instead encapsulates all the parameters
|
||||
// that deal with sending (or receiving). For sending, some of these
|
||||
// parameters will come from the remote SDP (eg; max-fps), and others can
|
||||
// only be determined by inspecting both local config and remote SDP (eg;
|
||||
// profile-level-id when level-asymmetry-allowed is 0).
|
||||
if (sending) {
|
||||
if (!codec->LoadSendParameters(remoteMsection)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!codec->LoadRecvParameters(remoteMsection)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (remoteMsection.GetMediaType() == SdpMediaSection::kAudio ||
|
||||
remoteMsection.GetMediaType() == SdpMediaSection::kVideo) {
|
||||
// Sanity-check that payload type can work with RTP
|
||||
uint16_t payloadType;
|
||||
if (!codec->GetPtAsInt(&payloadType) ||
|
||||
payloadType > UINT8_MAX) {
|
||||
JSEP_SET_ERROR("audio/video payload type is not an 8 bit unsigned int: "
|
||||
<< codec->mDefaultPt);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
negotiatedDetails->mCodecs.values.push_back(codec.release());
|
||||
break;
|
||||
}
|
||||
|
||||
if (negotiatedDetails->mCodecs.values.empty()) {
|
||||
JSEP_SET_ERROR("Failed to negotiate codec details for all codecs");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (answerMsection.GetAttributeList().HasAttribute(
|
||||
SdpAttribute::kExtmapAttribute)) {
|
||||
auto& extmap = answerMsection.GetAttributeList().GetExtmap().mExtmaps;
|
||||
for (auto i = extmap.begin(); i != extmap.end(); ++i) {
|
||||
negotiatedDetails->mExtmap[i->extensionname] = *i;
|
||||
}
|
||||
}
|
||||
|
||||
(*track)->SetNegotiatedDetails(Move(negotiatedDetails));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
JsepSessionImpl::UpdateTransport(const SdpMediaSection& msection,
|
||||
JsepTransport* transport)
|
||||
@ -1819,7 +1535,8 @@ JsepSessionImpl::ParseSdp(const std::string& sdp, UniquePtr<Sdp>* parsedp)
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& mediaAttrs = parsed->GetMediaSection(i).GetAttributeList();
|
||||
const SdpMediaSection& msection(parsed->GetMediaSection(i));
|
||||
auto& mediaAttrs = msection.GetAttributeList();
|
||||
|
||||
if (mediaAttrs.GetIceUfrag().empty()) {
|
||||
JSEP_SET_ERROR("Invalid description, no ice-ufrag attribute");
|
||||
@ -1882,6 +1599,19 @@ JsepSessionImpl::ParseSdp(const std::string& sdp, UniquePtr<Sdp>* parsedp)
|
||||
// Error has already been set
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (msection.GetMediaType() == SdpMediaSection::kAudio ||
|
||||
msection.GetMediaType() == SdpMediaSection::kVideo) {
|
||||
// Sanity-check that payload type can work with RTP
|
||||
for (const std::string& fmt : msection.GetFormats()) {
|
||||
uint16_t payloadType;
|
||||
// TODO (bug 1204099): Make this check for reserved ranges.
|
||||
if (!SdpHelper::GetPtAsInt(fmt, &payloadType) || payloadType > 127) {
|
||||
JSEP_SET_ERROR("audio/video payload type is too large: " << fmt);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*parsedp = Move(parsed);
|
||||
@ -2170,9 +1900,10 @@ JsepSessionImpl::CreateReceivingTrack(size_t mline,
|
||||
*track = new JsepTrack(msection.GetMediaType(),
|
||||
streamId,
|
||||
trackId,
|
||||
JsepTrack::kJsepTrackReceiving);
|
||||
sdp::kRecv);
|
||||
|
||||
(*track)->SetCNAME(mSdpHelper.GetCNAME(msection));
|
||||
(*track)->PopulateCodecs(mSupportedCodecs.values);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2532,10 +2263,6 @@ JsepSessionImpl::EnableOfferMsection(SdpMediaSection* msection)
|
||||
rv = SetRecvonlySsrc(msection);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
UpdateCodecsForOffer(msection->GetLevel());
|
||||
|
||||
AddCodecs(msection);
|
||||
|
||||
AddExtmap(msection);
|
||||
|
||||
std::ostringstream osMid;
|
||||
@ -2545,96 +2272,6 @@ JsepSessionImpl::EnableOfferMsection(SdpMediaSection* msection)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
JsepSessionImpl::GetAllPayloadTypes(
|
||||
const JsepTrackNegotiatedDetails& trackDetails,
|
||||
std::vector<uint8_t>* payloadTypesOut)
|
||||
{
|
||||
for (size_t j = 0; j < trackDetails.GetCodecCount(); ++j) {
|
||||
const JsepCodecDescription* codec;
|
||||
nsresult rv = trackDetails.GetCodec(j, &codec);
|
||||
if (NS_FAILED(rv)) {
|
||||
JSEP_SET_ERROR("GetCodec failed in GetAllPayloadTypes. rv="
|
||||
<< static_cast<uint32_t>(rv));
|
||||
MOZ_ASSERT(false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint16_t payloadType;
|
||||
if (!codec->GetPtAsInt(&payloadType) || payloadType > UINT8_MAX) {
|
||||
JSEP_SET_ERROR("Non-UINT8 payload type in GetAllPayloadTypes ("
|
||||
<< codec->mType
|
||||
<< "), this should have been caught sooner.");
|
||||
MOZ_ASSERT(false);
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
payloadTypesOut->push_back(payloadType);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// When doing bundle, if all else fails we can try to figure out which m-line a
|
||||
// given RTP packet belongs to by looking at the payload type field. This only
|
||||
// works, however, if that payload type appeared in only one m-section.
|
||||
// We figure that out here.
|
||||
nsresult
|
||||
JsepSessionImpl::SetUniquePayloadTypes()
|
||||
{
|
||||
// Maps to track details if no other track contains the payload type,
|
||||
// otherwise maps to nullptr.
|
||||
std::map<uint8_t, JsepTrackNegotiatedDetails*> payloadTypeToDetailsMap;
|
||||
|
||||
for (size_t i = 0; i < mRemoteTracks.size(); ++i) {
|
||||
auto track = mRemoteTracks[i].mTrack;
|
||||
|
||||
if (track->GetMediaType() == SdpMediaSection::kApplication) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* details = track->GetNegotiatedDetails();
|
||||
if (!details) {
|
||||
// Can happen if negotiation fails on a track
|
||||
continue;
|
||||
}
|
||||
|
||||
// Renegotiation might cause a PT to no longer be unique
|
||||
details->ClearUniquePayloadTypes();
|
||||
|
||||
std::vector<uint8_t> payloadTypesForTrack;
|
||||
nsresult rv = GetAllPayloadTypes(*details, &payloadTypesForTrack);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (auto j = payloadTypesForTrack.begin();
|
||||
j != payloadTypesForTrack.end();
|
||||
++j) {
|
||||
|
||||
if (payloadTypeToDetailsMap.count(*j)) {
|
||||
// Found in more than one track, not unique
|
||||
payloadTypeToDetailsMap[*j] = nullptr;
|
||||
} else {
|
||||
payloadTypeToDetailsMap[*j] = details;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = payloadTypeToDetailsMap.begin();
|
||||
i != payloadTypeToDetailsMap.end();
|
||||
++i) {
|
||||
uint8_t uniquePt = i->first;
|
||||
auto trackDetails = i->second;
|
||||
|
||||
if (!trackDetails) {
|
||||
continue;
|
||||
}
|
||||
|
||||
trackDetails->AddUniquePayloadType(uniquePt);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const Sdp*
|
||||
JsepSessionImpl::GetAnswer() const
|
||||
{
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "signaling/src/jsep/JsepTrack.h"
|
||||
#include "signaling/src/jsep/JsepSession.h"
|
||||
#include "signaling/src/jsep/JsepTrack.h"
|
||||
#include "signaling/src/jsep/JsepTrackImpl.h"
|
||||
#include "signaling/src/sdp/SipccSdpParser.h"
|
||||
#include "signaling/src/sdp/SdpHelper.h"
|
||||
#include "signaling/src/common/PtrVector.h"
|
||||
@ -44,8 +43,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~JsepSessionImpl();
|
||||
|
||||
// Implement JsepSession methods.
|
||||
virtual nsresult Init() override;
|
||||
|
||||
@ -171,7 +168,6 @@ private:
|
||||
struct JsepSendingTrack {
|
||||
RefPtr<JsepTrack> mTrack;
|
||||
Maybe<size_t> mAssignedMLine;
|
||||
bool mNegotiated;
|
||||
};
|
||||
|
||||
struct JsepReceivingTrack {
|
||||
@ -181,25 +177,11 @@ private:
|
||||
|
||||
// Non-const so it can set mLastError
|
||||
nsresult CreateGenericSDP(UniquePtr<Sdp>* sdp);
|
||||
void AddCodecs(SdpMediaSection* msection) const;
|
||||
void PopulateCodecsByLevel(size_t numLevels);
|
||||
void UpdateCodecsForOffer(size_t level);
|
||||
void ResetNonNegotiatedCodecs(size_t level);
|
||||
void GetNegotiatedPayloadTypes(size_t level,
|
||||
std::set<uint16_t>* types) const;
|
||||
void EnsureNoDuplicatePayloadTypes(size_t level);
|
||||
std::vector<JsepCodecDescription*> CreateCodecClones() const;
|
||||
void AddExtmap(SdpMediaSection* msection) const;
|
||||
void AddMid(const std::string& mid, SdpMediaSection* msection) const;
|
||||
void AddLocalIds(const JsepTrack& track, SdpMediaSection* msection) const;
|
||||
JsepCodecDescription* FindMatchingCodec(
|
||||
const std::string& pt,
|
||||
const SdpMediaSection& msection) const;
|
||||
const std::vector<SdpExtmapAttributeList::Extmap>* GetRtpExtensions(
|
||||
SdpMediaSection::MediaType type) const;
|
||||
|
||||
std::vector<JsepCodecDescription*> GetCommonCodecs(
|
||||
const SdpMediaSection& offerMsection);
|
||||
void AddCommonExtmaps(const SdpMediaSection& remoteMsection,
|
||||
SdpMediaSection* msection);
|
||||
nsresult SetupIds();
|
||||
@ -236,14 +218,13 @@ private:
|
||||
Sdp* sdp);
|
||||
nsresult BindLocalTracks(SdpMediaSection::MediaType mediatype,
|
||||
Sdp* sdp);
|
||||
nsresult BindTrackToMsection(JsepSendingTrack* track,
|
||||
SdpMediaSection* msection);
|
||||
nsresult EnsureRecvForRemoteTracks(SdpMediaSection::MediaType mediatype,
|
||||
Sdp* sdp,
|
||||
size_t* offerToReceive);
|
||||
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);
|
||||
@ -267,7 +248,8 @@ private:
|
||||
const SdpMediaSection& remoteMsection,
|
||||
Sdp* sdp);
|
||||
nsresult SetRecvonlySsrc(SdpMediaSection* msection);
|
||||
nsresult BindMatchingLocalTrackForAnswer(SdpMediaSection* msection);
|
||||
nsresult BindMatchingLocalTrackToAnswer(SdpMediaSection* msection);
|
||||
nsresult BindMatchingRemoteTrackToAnswer(SdpMediaSection* msection);
|
||||
nsresult DetermineAnswererSetupRole(const SdpMediaSection& remoteMsection,
|
||||
SdpSetupAttribute::Role* rolep);
|
||||
nsresult MakeNegotiatedTrackPair(const SdpMediaSection& remote,
|
||||
@ -276,11 +258,6 @@ private:
|
||||
bool usingBundle,
|
||||
size_t transportLevel,
|
||||
JsepTrackPair* trackPairOut);
|
||||
nsresult NegotiateTrack(const SdpMediaSection& remoteMsection,
|
||||
const SdpMediaSection& localMsection,
|
||||
JsepTrack::Direction,
|
||||
RefPtr<JsepTrack>* track);
|
||||
|
||||
void UpdateTransport(const SdpMediaSection& msection,
|
||||
JsepTransport* transport);
|
||||
|
||||
@ -292,9 +269,6 @@ private:
|
||||
|
||||
nsresult EnableOfferMsection(SdpMediaSection* msection);
|
||||
|
||||
nsresult SetUniquePayloadTypes();
|
||||
nsresult GetAllPayloadTypes(const JsepTrackNegotiatedDetails& trackDetails,
|
||||
std::vector<uint8_t>* payloadTypesOut);
|
||||
const Sdp* GetAnswer() const;
|
||||
|
||||
std::vector<JsepSendingTrack> mLocalTracks;
|
||||
@ -336,10 +310,6 @@ private:
|
||||
UniquePtr<Sdp> mPendingLocalDescription;
|
||||
UniquePtr<Sdp> mPendingRemoteDescription;
|
||||
PtrVector<JsepCodecDescription> mSupportedCodecs;
|
||||
// For each level, contains a full clone of
|
||||
// mSupportedCodecs. If any have been negotiated, this negotiation is taken
|
||||
// into account.
|
||||
std::vector<std::vector<JsepCodecDescription*>> mCodecsByLevel;
|
||||
std::string mLastError;
|
||||
SipccSdpParser mParser;
|
||||
SdpHelper mSdpHelper;
|
||||
|
303
media/webrtc/signaling/src/jsep/JsepTrack.cpp
Normal file
303
media/webrtc/signaling/src/jsep/JsepTrack.cpp
Normal file
@ -0,0 +1,303 @@
|
||||
/* 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/JsepTrack.h"
|
||||
#include "signaling/src/jsep/JsepCodecDescription.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
void
|
||||
JsepTrack::GetNegotiatedPayloadTypes(std::vector<uint16_t>* payloadTypes)
|
||||
{
|
||||
if (!mNegotiatedDetails) {
|
||||
return;
|
||||
}
|
||||
|
||||
GetPayloadTypes(mNegotiatedDetails->mCodecs.values, payloadTypes);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
JsepTrack::GetPayloadTypes(
|
||||
const std::vector<JsepCodecDescription*>& codecs,
|
||||
std::vector<uint16_t>* payloadTypes)
|
||||
{
|
||||
for (JsepCodecDescription* codec : codecs) {
|
||||
uint16_t pt;
|
||||
if (!codec->GetPtAsInt(&pt)) {
|
||||
MOZ_ASSERT(false);
|
||||
continue;
|
||||
}
|
||||
payloadTypes->push_back(pt);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JsepTrack::EnsureNoDuplicatePayloadTypes(
|
||||
std::vector<JsepCodecDescription*>* codecs)
|
||||
{
|
||||
std::set<uint16_t> uniquePayloadTypes;
|
||||
|
||||
for (JsepCodecDescription* codec : *codecs) {
|
||||
// We assume there are no dupes in negotiated codecs; unnegotiated codecs
|
||||
// need to change if there is a clash.
|
||||
if (!codec->mEnabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disable, and only re-enable if we can ensure it has a unique pt.
|
||||
codec->mEnabled = false;
|
||||
|
||||
uint16_t currentPt;
|
||||
if (!codec->GetPtAsInt(¤tPt)) {
|
||||
MOZ_ASSERT(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!uniquePayloadTypes.count(currentPt)) {
|
||||
codec->mEnabled = true;
|
||||
uniquePayloadTypes.insert(currentPt);
|
||||
continue;
|
||||
}
|
||||
|
||||
// |codec| cannot use its current payload type. Try to find another.
|
||||
for (uint16_t freePt = 96; freePt <= 127; ++freePt) {
|
||||
// Not super efficient, but readability is probably more important.
|
||||
if (!uniquePayloadTypes.count(freePt)) {
|
||||
uniquePayloadTypes.insert(freePt);
|
||||
codec->mEnabled = true;
|
||||
std::ostringstream os;
|
||||
os << freePt;
|
||||
codec->mDefaultPt = os.str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JsepTrack::PopulateCodecs(const std::vector<JsepCodecDescription*>& prototype)
|
||||
{
|
||||
for (const JsepCodecDescription* prototypeCodec : prototype) {
|
||||
if (prototypeCodec->mType == mType) {
|
||||
mPrototypeCodecs.values.push_back(prototypeCodec->Clone());
|
||||
mPrototypeCodecs.values.back()->mDirection = mDirection;
|
||||
}
|
||||
}
|
||||
|
||||
EnsureNoDuplicatePayloadTypes(&mPrototypeCodecs.values);
|
||||
}
|
||||
|
||||
void
|
||||
JsepTrack::AddToOffer(SdpMediaSection* offer) const
|
||||
{
|
||||
AddToMsection(mPrototypeCodecs.values, offer);
|
||||
}
|
||||
|
||||
void
|
||||
JsepTrack::AddToAnswer(const SdpMediaSection& offer,
|
||||
SdpMediaSection* answer) const
|
||||
{
|
||||
// We do not modify mPrototypeCodecs here, since we're only creating an answer. Once
|
||||
// offer/answer concludes, we will update mPrototypeCodecs.
|
||||
PtrVector<JsepCodecDescription> codecs;
|
||||
codecs.values = GetCodecClones();
|
||||
NegotiateCodecs(offer, &codecs.values);
|
||||
if (codecs.values.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddToMsection(codecs.values, answer);
|
||||
}
|
||||
|
||||
void
|
||||
JsepTrack::AddToMsection(const std::vector<JsepCodecDescription*>& codecs,
|
||||
SdpMediaSection* msection) const
|
||||
{
|
||||
MOZ_ASSERT(msection->GetMediaType() == mType);
|
||||
MOZ_ASSERT(!codecs.empty());
|
||||
|
||||
for (const JsepCodecDescription* codec : codecs) {
|
||||
codec->AddToMediaSection(*msection);
|
||||
}
|
||||
|
||||
if (mDirection == sdp::kSend) {
|
||||
if (msection->GetMediaType() != SdpMediaSection::kApplication) {
|
||||
msection->SetSsrcs(mSsrcs, mCNAME);
|
||||
msection->AddMsid(mStreamId, mTrackId);
|
||||
}
|
||||
msection->SetSending(true);
|
||||
} else {
|
||||
msection->SetReceiving(true);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<JsepCodecDescription*>
|
||||
JsepTrack::GetCodecClones() const
|
||||
{
|
||||
std::vector<JsepCodecDescription*> clones;
|
||||
for (const JsepCodecDescription* codec : mPrototypeCodecs.values) {
|
||||
clones.push_back(codec->Clone());
|
||||
}
|
||||
return clones;
|
||||
}
|
||||
|
||||
static bool
|
||||
CompareCodec(const JsepCodecDescription* lhs, const JsepCodecDescription* rhs)
|
||||
{
|
||||
return lhs->mStronglyPreferred && !rhs->mStronglyPreferred;
|
||||
}
|
||||
|
||||
void
|
||||
JsepTrack::NegotiateCodecs(
|
||||
const SdpMediaSection& remote,
|
||||
std::vector<JsepCodecDescription*>* codecs,
|
||||
const SdpMediaSection* answer,
|
||||
std::map<std::string, std::string>* formatChanges) const
|
||||
{
|
||||
PtrVector<JsepCodecDescription> unnegotiatedCodecs;
|
||||
std::swap(unnegotiatedCodecs.values, *codecs);
|
||||
|
||||
// Outer loop establishes the remote side's preference
|
||||
for (const std::string& fmt : remote.GetFormats()) {
|
||||
for (size_t i = 0; i < unnegotiatedCodecs.values.size(); ++i) {
|
||||
JsepCodecDescription* codec = unnegotiatedCodecs.values[i];
|
||||
if (!codec || !codec->mEnabled || !codec->Matches(fmt, remote)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string originalFormat = codec->mDefaultPt;
|
||||
if(codec->Negotiate(fmt, remote)) {
|
||||
codecs->push_back(codec);
|
||||
unnegotiatedCodecs.values[i] = nullptr;
|
||||
if (answer) {
|
||||
// Answer's formats are authoritative, and they might be different
|
||||
for (const std::string& answerFmt : answer->GetFormats()) {
|
||||
if (codec->Matches(answerFmt, *answer)) {
|
||||
codec->mDefaultPt = answerFmt;
|
||||
break; // We found the corresponding format in |answer|, bail
|
||||
}
|
||||
}
|
||||
}
|
||||
if (formatChanges) {
|
||||
(*formatChanges)[originalFormat] = codec->mDefaultPt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure strongly preferred codecs are up front, overriding the remote
|
||||
// side's preference.
|
||||
std::stable_sort(codecs->begin(), codecs->end(), CompareCodec);
|
||||
|
||||
// TODO(bug 814227): Remove this once we're ready to put multiple codecs in an
|
||||
// answer
|
||||
if (!codecs->empty()) {
|
||||
for (size_t i = 1; i < codecs->size(); ++i) {
|
||||
delete (*codecs)[i];
|
||||
(*codecs)[i] = nullptr;
|
||||
}
|
||||
codecs->resize(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JsepTrack::Negotiate(const SdpMediaSection& answer,
|
||||
const SdpMediaSection& remote)
|
||||
{
|
||||
UniquePtr<JsepTrackNegotiatedDetails> negotiatedDetails =
|
||||
MakeUnique<JsepTrackNegotiatedDetails>();
|
||||
|
||||
negotiatedDetails->mCodecs.values = GetCodecClones();
|
||||
std::map<std::string, std::string> formatChanges;
|
||||
NegotiateCodecs(remote,
|
||||
&negotiatedDetails->mCodecs.values,
|
||||
&answer,
|
||||
&formatChanges);
|
||||
|
||||
// Use |formatChanges| to update mPrototypeCodecs
|
||||
size_t insertPos = 0;
|
||||
for (size_t i = 0; i < mPrototypeCodecs.values.size(); ++i) {
|
||||
if (formatChanges.count(mPrototypeCodecs.values[i]->mDefaultPt)) {
|
||||
// Update the payload type to what was negotiated
|
||||
mPrototypeCodecs.values[i]->mDefaultPt =
|
||||
formatChanges[mPrototypeCodecs.values[i]->mDefaultPt];
|
||||
// Move this negotiated codec up front
|
||||
std::swap(mPrototypeCodecs.values[insertPos],
|
||||
mPrototypeCodecs.values[i]);
|
||||
++insertPos;
|
||||
}
|
||||
}
|
||||
|
||||
EnsureNoDuplicatePayloadTypes(&mPrototypeCodecs.values);
|
||||
|
||||
if (answer.GetAttributeList().HasAttribute(SdpAttribute::kExtmapAttribute)) {
|
||||
for (auto& extmapAttr : answer.GetAttributeList().GetExtmap().mExtmaps) {
|
||||
negotiatedDetails->mExtmap[extmapAttr.extensionname] = extmapAttr;
|
||||
}
|
||||
}
|
||||
|
||||
if ((mDirection == sdp::kRecv) &&
|
||||
remote.GetAttributeList().HasAttribute(SdpAttribute::kSsrcAttribute)) {
|
||||
for (auto& ssrcAttr : remote.GetAttributeList().GetSsrc().mSsrcs) {
|
||||
AddSsrc(ssrcAttr.ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
mNegotiatedDetails = Move(negotiatedDetails);
|
||||
}
|
||||
|
||||
// When doing bundle, if all else fails we can try to figure out which m-line a
|
||||
// given RTP packet belongs to by looking at the payload type field. This only
|
||||
// works, however, if that payload type appeared in only one m-section.
|
||||
// We figure that out here.
|
||||
/* static */
|
||||
void
|
||||
JsepTrack::SetUniquePayloadTypes(const std::vector<RefPtr<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) {
|
||||
if (track->GetMediaType() == SdpMediaSection::kApplication) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* details = track->GetNegotiatedDetails();
|
||||
if (!details) {
|
||||
// Can happen if negotiation fails on a track
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> payloadTypesForTrack;
|
||||
track->GetNegotiatedPayloadTypes(&payloadTypesForTrack);
|
||||
|
||||
for (uint16_t pt : payloadTypesForTrack) {
|
||||
if (payloadTypeToDetailsMap.count(pt)) {
|
||||
// Found in more than one track, not unique
|
||||
payloadTypeToDetailsMap[pt] = nullptr;
|
||||
} else {
|
||||
payloadTypeToDetailsMap[pt] = details;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto ptAndDetails : payloadTypeToDetailsMap) {
|
||||
uint16_t uniquePt = ptAndDetails.first;
|
||||
MOZ_ASSERT(uniquePt <= UINT8_MAX);
|
||||
auto trackDetails = ptAndDetails.second;
|
||||
|
||||
if (trackDetails) {
|
||||
trackDetails->mUniquePayloadTypes.push_back(
|
||||
static_cast<uint8_t>(uniquePt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -6,6 +6,8 @@
|
||||
#define _JSEPTRACK_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <mozilla/RefPtr.h>
|
||||
#include <mozilla/UniquePtr.h>
|
||||
@ -15,46 +17,66 @@
|
||||
|
||||
#include "signaling/src/jsep/JsepTransport.h"
|
||||
#include "signaling/src/sdp/Sdp.h"
|
||||
#include "signaling/src/sdp/SdpAttribute.h"
|
||||
#include "signaling/src/sdp/SdpMediaSection.h"
|
||||
#include "signaling/src/common/PtrVector.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Forward reference.
|
||||
struct JsepCodecDescription;
|
||||
class JsepCodecDescription;
|
||||
|
||||
class JsepTrackNegotiatedDetails
|
||||
{
|
||||
public:
|
||||
virtual ~JsepTrackNegotiatedDetails() {}
|
||||
size_t
|
||||
GetCodecCount() const
|
||||
{
|
||||
return mCodecs.values.size();
|
||||
}
|
||||
|
||||
virtual mozilla::SdpMediaSection::Protocol GetProtocol() const = 0;
|
||||
virtual Maybe<std::string> GetBandwidth(const std::string& type) const = 0;
|
||||
virtual size_t GetCodecCount() const = 0;
|
||||
virtual nsresult GetCodec(size_t index,
|
||||
const JsepCodecDescription** config) const = 0;
|
||||
virtual const SdpExtmapAttributeList::Extmap* GetExt(
|
||||
const std::string& ext_name) const = 0;
|
||||
virtual std::vector<uint8_t> GetUniquePayloadTypes() const = 0;
|
||||
const JsepCodecDescription*
|
||||
GetCodec(size_t index) const
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(index < mCodecs.values.size());
|
||||
return mCodecs.values[index];
|
||||
}
|
||||
|
||||
virtual void AddUniquePayloadType(uint8_t pt) = 0;
|
||||
virtual void ClearUniquePayloadTypes() = 0;
|
||||
const SdpExtmapAttributeList::Extmap*
|
||||
GetExt(const std::string& ext_name) const
|
||||
{
|
||||
auto it = mExtmap.find(ext_name);
|
||||
if (it != mExtmap.end()) {
|
||||
return &it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> GetUniquePayloadTypes() const
|
||||
{
|
||||
return mUniquePayloadTypes;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class JsepTrack;
|
||||
|
||||
std::map<std::string, SdpExtmapAttributeList::Extmap> mExtmap;
|
||||
std::vector<uint8_t> mUniquePayloadTypes;
|
||||
PtrVector<JsepCodecDescription> mCodecs;
|
||||
};
|
||||
|
||||
class JsepTrack
|
||||
{
|
||||
public:
|
||||
enum Direction { kJsepTrackSending, kJsepTrackReceiving };
|
||||
|
||||
JsepTrack(mozilla::SdpMediaSection::MediaType type,
|
||||
const std::string& streamid,
|
||||
const std::string& trackid,
|
||||
Direction direction = kJsepTrackSending)
|
||||
sdp::Direction direction = sdp::kSend)
|
||||
: mType(type),
|
||||
mStreamId(streamid),
|
||||
mTrackId(trackid),
|
||||
mDirection(direction)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
virtual mozilla::SdpMediaSection::MediaType
|
||||
GetMediaType() const
|
||||
@ -98,7 +120,7 @@ public:
|
||||
mCNAME = cname;
|
||||
}
|
||||
|
||||
virtual Direction
|
||||
virtual sdp::Direction
|
||||
GetDirection() const
|
||||
{
|
||||
return mDirection;
|
||||
@ -116,6 +138,17 @@ public:
|
||||
mSsrcs.push_back(ssrc);
|
||||
}
|
||||
|
||||
virtual void PopulateCodecs(
|
||||
const std::vector<JsepCodecDescription*>& prototype);
|
||||
virtual void AddToOffer(SdpMediaSection* offer) const;
|
||||
virtual void AddToAnswer(const SdpMediaSection& offer,
|
||||
SdpMediaSection* answer) const;
|
||||
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);
|
||||
|
||||
// This will be set when negotiation is carried out.
|
||||
virtual const JsepTrackNegotiatedDetails*
|
||||
GetNegotiatedDetails() const
|
||||
@ -135,11 +168,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This is for JsepSession's use.
|
||||
virtual void
|
||||
SetNegotiatedDetails(UniquePtr<JsepTrackNegotiatedDetails> details)
|
||||
ClearNegotiatedDetails()
|
||||
{
|
||||
mNegotiatedDetails = Move(details);
|
||||
mNegotiatedDetails.reset();
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(JsepTrack);
|
||||
@ -148,11 +180,34 @@ protected:
|
||||
virtual ~JsepTrack() {}
|
||||
|
||||
private:
|
||||
virtual std::vector<JsepCodecDescription*> GetCodecClones() const;
|
||||
static void EnsureNoDuplicatePayloadTypes(
|
||||
std::vector<JsepCodecDescription*>* codecs);
|
||||
static void GetPayloadTypes(
|
||||
const std::vector<JsepCodecDescription*>& codecs,
|
||||
std::vector<uint16_t>* pts);
|
||||
static void EnsurePayloadTypeIsUnique(std::set<uint16_t>* uniquePayloadTypes,
|
||||
JsepCodecDescription* codec);
|
||||
virtual void AddToMsection(const std::vector<JsepCodecDescription*>& codecs,
|
||||
SdpMediaSection* msection) const;
|
||||
|
||||
// |answer| is set when performing the final negotiation on completion of
|
||||
// offer/answer, and is used to update the formats in |codecs|, since the
|
||||
// answer is authoritative. |formatChanges| is also set on completion of
|
||||
// offer/answer, and records how the formats in |codecs| were changed, which
|
||||
// is used by |Negotiate| to update |mPrototypeCodecs|.
|
||||
virtual void NegotiateCodecs(
|
||||
const SdpMediaSection& remote,
|
||||
std::vector<JsepCodecDescription*>* codecs,
|
||||
const SdpMediaSection* answer = nullptr,
|
||||
std::map<std::string, std::string>* formatChanges = nullptr) const;
|
||||
|
||||
const mozilla::SdpMediaSection::MediaType mType;
|
||||
std::string mStreamId;
|
||||
std::string mTrackId;
|
||||
std::string mCNAME;
|
||||
const Direction mDirection;
|
||||
const sdp::Direction mDirection;
|
||||
PtrVector<JsepCodecDescription> mPrototypeCodecs;
|
||||
UniquePtr<JsepTrackNegotiatedDetails> mNegotiatedDetails;
|
||||
std::vector<uint32_t> mSsrcs;
|
||||
};
|
||||
|
@ -1,92 +0,0 @@
|
||||
/* 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 _JSEPTRACKIMPL_H_
|
||||
#define _JSEPTRACKIMPL_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <mozilla/RefPtr.h>
|
||||
#include <mozilla/UniquePtr.h>
|
||||
|
||||
#include "signaling/src/jsep/JsepCodecDescription.h"
|
||||
#include "signaling/src/jsep/JsepTrack.h"
|
||||
#include "signaling/src/sdp/Sdp.h"
|
||||
#include "signaling/src/sdp/SdpMediaSection.h"
|
||||
#include "signaling/src/common/PtrVector.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class JsepTrackNegotiatedDetailsImpl : public JsepTrackNegotiatedDetails
|
||||
{
|
||||
public:
|
||||
virtual ~JsepTrackNegotiatedDetailsImpl()
|
||||
{}
|
||||
|
||||
// Implement JsepTrackNegotiatedDetails.
|
||||
virtual mozilla::SdpMediaSection::Protocol
|
||||
GetProtocol() const override
|
||||
{
|
||||
return mProtocol;
|
||||
}
|
||||
virtual Maybe<std::string>
|
||||
GetBandwidth(const std::string& type) const override
|
||||
{
|
||||
return mBandwidth;
|
||||
}
|
||||
virtual size_t
|
||||
GetCodecCount() const override
|
||||
{
|
||||
return mCodecs.values.size();
|
||||
}
|
||||
virtual nsresult
|
||||
GetCodec(size_t index, const JsepCodecDescription** config) const override
|
||||
{
|
||||
if (index >= mCodecs.values.size()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
*config = mCodecs.values[index];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual const SdpExtmapAttributeList::Extmap*
|
||||
GetExt(const std::string& ext_name) const override
|
||||
{
|
||||
auto it = mExtmap.find(ext_name);
|
||||
if (it != mExtmap.end()) {
|
||||
return &it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual std::vector<uint8_t> GetUniquePayloadTypes() const override
|
||||
{
|
||||
return mUniquePayloadTypes;
|
||||
}
|
||||
|
||||
virtual void AddUniquePayloadType(uint8_t pt) override
|
||||
{
|
||||
mUniquePayloadTypes.push_back(pt);
|
||||
}
|
||||
|
||||
virtual void ClearUniquePayloadTypes() override
|
||||
{
|
||||
mUniquePayloadTypes.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
// Make these friends to JsepSessionImpl to avoid having to
|
||||
// write setters.
|
||||
friend class JsepSessionImpl;
|
||||
|
||||
mozilla::SdpMediaSection::Protocol mProtocol;
|
||||
Maybe<std::string> mBandwidth;
|
||||
PtrVector<JsepCodecDescription> mCodecs;
|
||||
std::map<std::string, SdpExtmapAttributeList::Extmap> mExtmap;
|
||||
std::vector<uint8_t> mUniquePayloadTypes;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -281,8 +281,7 @@ MediaPipelineFactory::GetTransportParameters(
|
||||
}
|
||||
|
||||
if (aTrackPair.mBundleLevel.isSome()) {
|
||||
bool receiving =
|
||||
aTrack.GetDirection() == JsepTrack::Direction::kJsepTrackReceiving;
|
||||
bool receiving = aTrack.GetDirection() == sdp::kRecv;
|
||||
|
||||
*aFilterOut = new MediaPipelineFilter;
|
||||
|
||||
@ -329,8 +328,7 @@ MediaPipelineFactory::CreateOrUpdateMediaPipeline(
|
||||
|
||||
MOZ_ASSERT(aTrackPair.mRtpTransport);
|
||||
|
||||
bool receiving =
|
||||
aTrack.GetDirection() == JsepTrack::Direction::kJsepTrackReceiving;
|
||||
bool receiving = aTrack.GetDirection() == sdp::kRecv;
|
||||
|
||||
size_t level;
|
||||
RefPtr<TransportFlow> rtpFlow;
|
||||
@ -570,6 +568,15 @@ MediaPipelineFactory::CreateMediaPipelineSending(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static const JsepCodecDescription*
|
||||
GetBestCodec(const JsepTrackNegotiatedDetails& details)
|
||||
{
|
||||
if (details.GetCodecCount()) {
|
||||
return details.GetCodec(0);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaPipelineFactory::GetOrCreateAudioConduit(
|
||||
const JsepTrackPair& aTrackPair,
|
||||
@ -582,8 +589,7 @@ MediaPipelineFactory::GetOrCreateAudioConduit(
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bool receiving =
|
||||
aTrack.GetDirection() == JsepTrack::Direction::kJsepTrackReceiving;
|
||||
bool receiving = aTrack.GetDirection() == sdp::kRecv;
|
||||
|
||||
RefPtr<AudioSessionConduit> conduit =
|
||||
mPCMedia->GetAudioConduit(aTrackPair.mLevel);
|
||||
@ -598,27 +604,21 @@ MediaPipelineFactory::GetOrCreateAudioConduit(
|
||||
mPCMedia->AddAudioConduit(aTrackPair.mLevel, conduit);
|
||||
}
|
||||
|
||||
size_t numCodecs = aTrack.GetNegotiatedDetails()->GetCodecCount();
|
||||
if (numCodecs == 0) {
|
||||
if (!GetBestCodec(*aTrack.GetNegotiatedDetails())) {
|
||||
MOZ_MTLOG(ML_ERROR, "Can't set up a conduit with 0 codecs");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
size_t numCodecs = aTrack.GetNegotiatedDetails()->GetCodecCount();
|
||||
if (receiving) {
|
||||
PtrVector<AudioCodecConfig> configs;
|
||||
|
||||
for (size_t i = 0; i < numCodecs; i++) {
|
||||
const JsepCodecDescription* cdesc;
|
||||
nsresult rv = aTrack.GetNegotiatedDetails()->GetCodec(i, &cdesc);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Failed to get codec from jsep track, rv="
|
||||
<< static_cast<uint32_t>(rv));
|
||||
return rv;
|
||||
}
|
||||
const JsepCodecDescription* cdesc =
|
||||
aTrack.GetNegotiatedDetails()->GetCodec(i);
|
||||
|
||||
AudioCodecConfig* configRaw;
|
||||
rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
|
||||
nsresult rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -652,18 +652,11 @@ MediaPipelineFactory::GetOrCreateAudioConduit(
|
||||
|
||||
conduit->SetLocalCNAME(aTrack.GetCNAME().c_str());
|
||||
|
||||
const JsepCodecDescription* cdesc;
|
||||
// Best codec.
|
||||
nsresult rv = aTrack.GetNegotiatedDetails()->GetCodec(0, &cdesc);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Failed to get codec from jsep track, rv="
|
||||
<< static_cast<uint32_t>(rv));
|
||||
return rv;
|
||||
}
|
||||
const JsepCodecDescription* cdesc =
|
||||
GetBestCodec(*aTrack.GetNegotiatedDetails());
|
||||
|
||||
AudioCodecConfig* configRaw;
|
||||
rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
|
||||
nsresult rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -706,8 +699,7 @@ MediaPipelineFactory::GetOrCreateVideoConduit(
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
bool receiving =
|
||||
aTrack.GetDirection() == JsepTrack::Direction::kJsepTrackReceiving;
|
||||
bool receiving = aTrack.GetDirection() == sdp::kRecv;
|
||||
|
||||
RefPtr<VideoSessionConduit> conduit =
|
||||
mPCMedia->GetVideoConduit(aTrackPair.mLevel);
|
||||
@ -715,35 +707,35 @@ MediaPipelineFactory::GetOrCreateVideoConduit(
|
||||
if (!conduit) {
|
||||
conduit = VideoSessionConduit::Create();
|
||||
if (!conduit) {
|
||||
MOZ_MTLOG(ML_ERROR, "Could not create audio conduit");
|
||||
MOZ_MTLOG(ML_ERROR, "Could not create video conduit");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mPCMedia->AddVideoConduit(aTrackPair.mLevel, conduit);
|
||||
}
|
||||
|
||||
size_t numCodecs = aTrack.GetNegotiatedDetails()->GetCodecCount();
|
||||
if (numCodecs == 0) {
|
||||
if (!GetBestCodec(*aTrack.GetNegotiatedDetails())) {
|
||||
MOZ_MTLOG(ML_ERROR, "Can't set up a conduit with 0 codecs");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
size_t numCodecs = aTrack.GetNegotiatedDetails()->GetCodecCount();
|
||||
|
||||
bool configuredH264 = false;
|
||||
if (receiving) {
|
||||
PtrVector<VideoCodecConfig> configs;
|
||||
|
||||
for (size_t i = 0; i < numCodecs; i++) {
|
||||
const JsepCodecDescription* cdesc;
|
||||
const JsepCodecDescription* cdesc =
|
||||
aTrack.GetNegotiatedDetails()->GetCodec(i);
|
||||
|
||||
nsresult rv = aTrack.GetNegotiatedDetails()->GetCodec(i, &cdesc);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Failed to get codec from jsep track, rv="
|
||||
<< static_cast<uint32_t>(rv));
|
||||
return rv;
|
||||
// We can only handle configuring one recv H264 codec
|
||||
if (configuredH264 && (cdesc->mName == "H264")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
VideoCodecConfig* configRaw;
|
||||
rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
|
||||
nsresult rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -752,6 +744,9 @@ MediaPipelineFactory::GetOrCreateVideoConduit(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cdesc->mName == "H264") {
|
||||
configuredH264 = true;
|
||||
}
|
||||
configs.values.push_back(config.release());
|
||||
}
|
||||
|
||||
@ -782,18 +777,11 @@ MediaPipelineFactory::GetOrCreateVideoConduit(
|
||||
|
||||
conduit->SetLocalCNAME(aTrack.GetCNAME().c_str());
|
||||
|
||||
const JsepCodecDescription* cdesc;
|
||||
// Best codec.
|
||||
nsresult rv = aTrack.GetNegotiatedDetails()->GetCodec(0, &cdesc);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Failed to get codec from jsep track, rv="
|
||||
<< static_cast<uint32_t>(rv));
|
||||
return rv;
|
||||
}
|
||||
const JsepCodecDescription* cdesc =
|
||||
GetBestCodec(*aTrack.GetNegotiatedDetails());
|
||||
|
||||
VideoCodecConfig* configRaw;
|
||||
rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
|
||||
nsresult rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -389,6 +389,7 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal)
|
||||
, mUuidGen(MakeUnique<PCUuidGenerator>())
|
||||
, mNumAudioStreams(0)
|
||||
, mNumVideoStreams(0)
|
||||
, mHaveConfiguredCodecs(false)
|
||||
, mHaveDataStream(false)
|
||||
, mAddCandidateErrorCount(0)
|
||||
, mTrickle(true) // TODO(ekr@rtfm.com): Use pref
|
||||
@ -929,6 +930,11 @@ class CompareCodecPriority {
|
||||
|
||||
nsresult
|
||||
PeerConnectionImpl::ConfigureJsepSessionCodecs() {
|
||||
if (mHaveConfiguredCodecs) {
|
||||
return NS_OK;
|
||||
}
|
||||
mHaveConfiguredCodecs = true;
|
||||
|
||||
#if !defined(MOZILLA_XPCOMRT_API)
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIPrefService> prefs =
|
||||
@ -1150,15 +1156,8 @@ PeerConnectionImpl::GetDatachannelParameters(
|
||||
for (size_t i = 0;
|
||||
i < trackPair.mSending->GetNegotiatedDetails()->GetCodecCount();
|
||||
++i) {
|
||||
const JsepCodecDescription* codec;
|
||||
nsresult res =
|
||||
trackPair.mSending->GetNegotiatedDetails()->GetCodec(i, &codec);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
CSFLogError(logTag, "%s: Failed getting codec for m=application.",
|
||||
__FUNCTION__);
|
||||
continue;
|
||||
}
|
||||
const JsepCodecDescription* codec =
|
||||
trackPair.mSending->GetNegotiatedDetails()->GetCodec(i);
|
||||
|
||||
if (codec->mType != SdpMediaSection::kApplication) {
|
||||
CSFLogError(logTag, "%s: Codec type for m=application was %u, this "
|
||||
@ -1194,6 +1193,63 @@ PeerConnectionImpl::GetDatachannelParameters(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
PeerConnectionImpl::DeferredAddTrackToJsepSession(
|
||||
const std::string& pcHandle,
|
||||
SdpMediaSection::MediaType type,
|
||||
const std::string& streamId,
|
||||
const std::string& trackId)
|
||||
{
|
||||
PeerConnectionWrapper wrapper(pcHandle);
|
||||
|
||||
if (wrapper.impl()) {
|
||||
if (!PeerConnectionCtx::GetInstance()->isReady()) {
|
||||
MOZ_CRASH("Why is DeferredAddTrackToJsepSession being executed when the "
|
||||
"PeerConnectionCtx isn't ready?");
|
||||
}
|
||||
wrapper.impl()->AddTrackToJsepSession(type, streamId, trackId);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
PeerConnectionImpl::AddTrackToJsepSession(SdpMediaSection::MediaType type,
|
||||
const std::string& streamId,
|
||||
const std::string& trackId)
|
||||
{
|
||||
if (!PeerConnectionCtx::GetInstance()->isReady()) {
|
||||
// We are not ready to configure codecs for this track. We need to defer.
|
||||
PeerConnectionCtx::GetInstance()->queueJSEPOperation(
|
||||
WrapRunnableNM(DeferredAddTrackToJsepSession,
|
||||
mHandle,
|
||||
type,
|
||||
streamId,
|
||||
trackId));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult res = ConfigureJsepSessionCodecs();
|
||||
if (NS_FAILED(res)) {
|
||||
CSFLogError(logTag, "Failed to configure codecs");
|
||||
return res;
|
||||
}
|
||||
|
||||
res = mJsepSession->AddTrack(
|
||||
new JsepTrack(type, streamId, trackId, sdp::kSend));
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
std::string errorString = mJsepSession->GetLastError();
|
||||
CSFLogError(logTag, "%s (%s) : pc = %s, error = %s",
|
||||
__FUNCTION__,
|
||||
type == SdpMediaSection::kAudio ? "audio" : "video",
|
||||
mHandle.c_str(),
|
||||
errorString.c_str());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PeerConnectionImpl::InitializeDataChannel()
|
||||
{
|
||||
@ -1319,7 +1375,7 @@ PeerConnectionImpl::CreateDataChannel(const nsAString& aLabel,
|
||||
mozilla::SdpMediaSection::kApplication,
|
||||
streamId,
|
||||
trackId,
|
||||
JsepTrack::kJsepTrackSending));
|
||||
sdp::kSend));
|
||||
|
||||
rv = mJsepSession->AddTrack(track);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -2077,6 +2133,7 @@ PeerConnectionImpl::AddTrack(MediaStreamTrack& aTrack,
|
||||
CSFLogError(logTag, "%s: At least one stream arg required", __FUNCTION__);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return AddTrack(aTrack, aStreams[0]);
|
||||
}
|
||||
|
||||
@ -2105,16 +2162,9 @@ PeerConnectionImpl::AddTrack(MediaStreamTrack& aTrack,
|
||||
}
|
||||
|
||||
if (aTrack.AsAudioStreamTrack()) {
|
||||
res = mJsepSession->AddTrack(new JsepTrack(
|
||||
mozilla::SdpMediaSection::kAudio,
|
||||
streamId,
|
||||
trackId,
|
||||
JsepTrack::kJsepTrackSending));
|
||||
res = AddTrackToJsepSession(SdpMediaSection::kAudio, streamId, trackId);
|
||||
if (NS_FAILED(res)) {
|
||||
std::string errorString = mJsepSession->GetLastError();
|
||||
CSFLogError(logTag, "%s (audio) : pc = %s, error = %s",
|
||||
__FUNCTION__, mHandle.c_str(), errorString.c_str());
|
||||
return NS_ERROR_FAILURE;
|
||||
return res;
|
||||
}
|
||||
mNumAudioStreams++;
|
||||
}
|
||||
@ -2128,16 +2178,9 @@ PeerConnectionImpl::AddTrack(MediaStreamTrack& aTrack,
|
||||
}
|
||||
#endif
|
||||
|
||||
res = mJsepSession->AddTrack(new JsepTrack(
|
||||
mozilla::SdpMediaSection::kVideo,
|
||||
streamId,
|
||||
trackId,
|
||||
JsepTrack::kJsepTrackSending));
|
||||
res = AddTrackToJsepSession(SdpMediaSection::kVideo, streamId, trackId);
|
||||
if (NS_FAILED(res)) {
|
||||
std::string errorString = mJsepSession->GetLastError();
|
||||
CSFLogError(logTag, "%s (video) : pc = %s, error = %s",
|
||||
__FUNCTION__, mHandle.c_str(), errorString.c_str());
|
||||
return NS_ERROR_FAILURE;
|
||||
return res;
|
||||
}
|
||||
mNumVideoStreams++;
|
||||
}
|
||||
|
@ -673,6 +673,15 @@ private:
|
||||
const mozilla::JsepApplicationCodecDescription** codec,
|
||||
uint16_t* level) const;
|
||||
|
||||
static void DeferredAddTrackToJsepSession(const std::string& pcHandle,
|
||||
SdpMediaSection::MediaType type,
|
||||
const std::string& streamId,
|
||||
const std::string& trackId);
|
||||
|
||||
nsresult AddTrackToJsepSession(SdpMediaSection::MediaType type,
|
||||
const std::string& streamId,
|
||||
const std::string& trackId);
|
||||
|
||||
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
|
||||
static void GetStatsForPCObserver_s(
|
||||
const std::string& pcHandle,
|
||||
@ -777,6 +786,7 @@ private:
|
||||
// Bug 840728.
|
||||
int mNumAudioStreams;
|
||||
int mNumVideoStreams;
|
||||
bool mHaveConfiguredCodecs;
|
||||
|
||||
bool mHaveDataStream;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "signaling/src/sdp/SdpAttribute.h"
|
||||
#include "signaling/src/sdp/SdpHelper.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
@ -941,6 +942,29 @@ SdpSimulcastAttribute::Version::Parse(std::istream& is, std::string* error)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SdpSimulcastAttribute::Version::AppendAsStrings(
|
||||
std::vector<std::string>* formats) const
|
||||
{
|
||||
for (uint16_t pt : choices) {
|
||||
std::ostringstream os;
|
||||
os << pt;
|
||||
formats->push_back(os.str());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SdpSimulcastAttribute::Version::AddChoice(const std::string& pt)
|
||||
{
|
||||
uint16_t ptAsInt;
|
||||
if (!SdpHelper::GetPtAsInt(pt, &ptAsInt)) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
choices.push_back(ptAsInt);
|
||||
}
|
||||
|
||||
void
|
||||
SdpSimulcastAttribute::Versions::Serialize(std::ostream& os) const
|
||||
{
|
||||
|
@ -178,14 +178,11 @@ inline std::ostream& operator<<(std::ostream& os,
|
||||
class SdpDirectionAttribute : public SdpAttribute
|
||||
{
|
||||
public:
|
||||
static const unsigned kSendFlag = 1;
|
||||
static const unsigned kRecvFlag = 1 << 1;
|
||||
|
||||
enum Direction {
|
||||
kInactive = 0,
|
||||
kSendonly = kSendFlag,
|
||||
kRecvonly = kRecvFlag,
|
||||
kSendrecv = kSendFlag | kRecvFlag
|
||||
kSendonly = sdp::kSend,
|
||||
kRecvonly = sdp::kRecv,
|
||||
kSendrecv = sdp::kSend | sdp::kRecv
|
||||
};
|
||||
|
||||
explicit SdpDirectionAttribute(Direction value)
|
||||
@ -1153,6 +1150,14 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
Fmtp(const std::string& aFormat, const std::string& aParametersString,
|
||||
const Parameters& aParameters)
|
||||
: format(aFormat),
|
||||
parameters_string(aParametersString),
|
||||
parameters(aParameters.Clone())
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Rip all of this out when we have move semantics in the stl.
|
||||
Fmtp(const Fmtp& orig) { *this = orig; }
|
||||
|
||||
@ -1323,6 +1328,8 @@ public:
|
||||
return !choices.empty();
|
||||
}
|
||||
bool Parse(std::istream& is, std::string* error);
|
||||
void AppendAsStrings(std::vector<std::string>* formats) const;
|
||||
void AddChoice(const std::string& pt);
|
||||
|
||||
std::vector<uint16_t> choices;
|
||||
};
|
||||
|
@ -46,6 +46,12 @@ inline std::ostream& operator<<(std::ostream& os, sdp::AddrType t)
|
||||
MOZ_CRASH("Unknown AddrType");
|
||||
}
|
||||
|
||||
enum Direction {
|
||||
// Start at 1 so these can be used as flags
|
||||
kSend = 1,
|
||||
kRecv = 2
|
||||
};
|
||||
|
||||
} // namespace sdp
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -118,7 +118,7 @@ SdpHelper::MsectionIsDisabled(const SdpMediaSection& msection) const
|
||||
}
|
||||
|
||||
void
|
||||
SdpHelper::DisableMsection(Sdp* sdp, SdpMediaSection* msection) const
|
||||
SdpHelper::DisableMsection(Sdp* sdp, SdpMediaSection* msection)
|
||||
{
|
||||
// Make sure to remove the mid from any group attributes
|
||||
if (msection->GetAttributeList().HasAttribute(SdpAttribute::kMidAttribute)) {
|
||||
@ -554,28 +554,6 @@ SdpHelper::FindMsectionByMid(Sdp& sdp,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SdpHelper::SetSsrcs(const std::vector<uint32_t>& ssrcs,
|
||||
const std::string& cname,
|
||||
SdpMediaSection* msection) const
|
||||
{
|
||||
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 += cname;
|
||||
ssrcAttr->PushEntry(ssrc, cnameAttr);
|
||||
}
|
||||
|
||||
msection->GetAttributeList().SetAttribute(ssrcAttr.release());
|
||||
}
|
||||
|
||||
nsresult
|
||||
SdpHelper::CopyStickyParams(const SdpMediaSection& source,
|
||||
SdpMediaSection* dest)
|
||||
|
@ -36,7 +36,7 @@ class SdpHelper {
|
||||
size_t level);
|
||||
|
||||
bool MsectionIsDisabled(const SdpMediaSection& msection) const;
|
||||
void DisableMsection(Sdp* sdp, SdpMediaSection* msection) const;
|
||||
static void DisableMsection(Sdp* sdp, SdpMediaSection* msection);
|
||||
|
||||
// Maps each mid to the m-section that is the master of its bundle.
|
||||
// Mids that do not appear in an a=group:BUNDLE do not appear here.
|
||||
@ -81,9 +81,6 @@ class SdpHelper {
|
||||
Sdp* sdp) const;
|
||||
|
||||
std::string GetCNAME(const SdpMediaSection& msection) const;
|
||||
void SetSsrcs(const std::vector<uint32_t>& ssrcs,
|
||||
const std::string& cname,
|
||||
SdpMediaSection* msection) const;
|
||||
|
||||
SdpMediaSection* FindMsectionByMid(Sdp& sdp,
|
||||
const std::string& mid) const;
|
||||
|
160
media/webrtc/signaling/src/sdp/SdpMediaSection.cpp
Normal file
160
media/webrtc/signaling/src/sdp/SdpMediaSection.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/sdp/SdpMediaSection.h"
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
const SdpFmtpAttributeList::Parameters*
|
||||
SdpMediaSection::FindFmtp(const std::string& pt) const
|
||||
{
|
||||
const SdpAttributeList& attrs = GetAttributeList();
|
||||
|
||||
if (attrs.HasAttribute(SdpAttribute::kFmtpAttribute)) {
|
||||
for (auto& fmtpAttr : attrs.GetFmtp().mFmtps) {
|
||||
if (fmtpAttr.format == pt && fmtpAttr.parameters) {
|
||||
return fmtpAttr.parameters.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SdpMediaSection::SetFmtp(const SdpFmtpAttributeList::Fmtp& fmtpToSet)
|
||||
{
|
||||
UniquePtr<SdpFmtpAttributeList> fmtps(new SdpFmtpAttributeList);
|
||||
|
||||
if (GetAttributeList().HasAttribute(SdpAttribute::kFmtpAttribute)) {
|
||||
*fmtps = GetAttributeList().GetFmtp();
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (SdpFmtpAttributeList::Fmtp& fmtp : fmtps->mFmtps) {
|
||||
if (fmtp.format == fmtpToSet.format) {
|
||||
fmtp = fmtpToSet;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
fmtps->mFmtps.push_back(fmtpToSet);
|
||||
}
|
||||
|
||||
GetAttributeList().SetAttribute(fmtps.release());
|
||||
}
|
||||
|
||||
const SdpRtpmapAttributeList::Rtpmap*
|
||||
SdpMediaSection::FindRtpmap(const std::string& pt) const
|
||||
{
|
||||
auto& attrs = GetAttributeList();
|
||||
if (!attrs.HasAttribute(SdpAttribute::kRtpmapAttribute)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SdpRtpmapAttributeList& rtpmap = attrs.GetRtpmap();
|
||||
if (!rtpmap.HasEntry(pt)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &rtpmap.GetEntry(pt);
|
||||
}
|
||||
|
||||
const SdpSctpmapAttributeList::Sctpmap*
|
||||
SdpMediaSection::FindSctpmap(const std::string& pt) const
|
||||
{
|
||||
auto& attrs = GetAttributeList();
|
||||
if (!attrs.HasAttribute(SdpAttribute::kSctpmapAttribute)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SdpSctpmapAttributeList& sctpmap = attrs.GetSctpmap();
|
||||
if (!sctpmap.HasEntry(pt)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &sctpmap.GetEntry(pt);
|
||||
}
|
||||
|
||||
bool
|
||||
SdpMediaSection::HasRtcpFb(const std::string& pt,
|
||||
SdpRtcpFbAttributeList::Type type,
|
||||
const std::string& subType) const
|
||||
{
|
||||
const SdpAttributeList& attrs(GetAttributeList());
|
||||
|
||||
if (!attrs.HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& rtcpfb : attrs.GetRtcpFb().mFeedbacks) {
|
||||
if (rtcpfb.type == type) {
|
||||
if (rtcpfb.pt == "*" || rtcpfb.pt == pt) {
|
||||
if (rtcpfb.parameter == subType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SdpRtcpFbAttributeList
|
||||
SdpMediaSection::GetRtcpFbs() const
|
||||
{
|
||||
SdpRtcpFbAttributeList result;
|
||||
if (GetAttributeList().HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
|
||||
result = GetAttributeList().GetRtcpFb();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
SdpMediaSection::SetRtcpFbs(const SdpRtcpFbAttributeList& rtcpfbs)
|
||||
{
|
||||
if (rtcpfbs.mFeedbacks.empty()) {
|
||||
GetAttributeList().RemoveAttribute(SdpAttribute::kRtcpFbAttribute);
|
||||
return;
|
||||
}
|
||||
|
||||
GetAttributeList().SetAttribute(new SdpRtcpFbAttributeList(rtcpfbs));
|
||||
}
|
||||
|
||||
void
|
||||
SdpMediaSection::SetSsrcs(const std::vector<uint32_t>& ssrcs,
|
||||
const std::string& cname)
|
||||
{
|
||||
if (ssrcs.empty()) {
|
||||
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 += cname;
|
||||
ssrcAttr->PushEntry(ssrc, cnameAttr);
|
||||
}
|
||||
|
||||
GetAttributeList().SetAttribute(ssrcAttr.release());
|
||||
}
|
||||
|
||||
void
|
||||
SdpMediaSection::AddMsid(const std::string& id, const std::string& appdata)
|
||||
{
|
||||
UniquePtr<SdpMsidAttributeList> msids(new SdpMsidAttributeList);
|
||||
if (GetAttributeList().HasAttribute(SdpAttribute::kMsidAttribute)) {
|
||||
msids->mMsids = GetAttributeList().GetMsid().mMsids;
|
||||
}
|
||||
msids->PushEntry(id, appdata);
|
||||
GetAttributeList().SetAttribute(msids.release());
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -12,8 +12,7 @@
|
||||
#include "signaling/src/sdp/SdpAttributeList.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "signaling/src/sdp/SdpEnum.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
@ -81,6 +80,8 @@ public:
|
||||
virtual uint32_t GetBandwidth(const std::string& type) const = 0;
|
||||
virtual const std::vector<std::string>& GetFormats() const = 0;
|
||||
|
||||
std::vector<std::string> GetFormatsForSimulcastVersion(
|
||||
size_t simulcastVersion, bool send, bool recv) const;
|
||||
virtual const SdpAttributeList& GetAttributeList() const = 0;
|
||||
virtual SdpAttributeList& GetAttributeList() = 0;
|
||||
|
||||
@ -104,20 +105,20 @@ public:
|
||||
inline bool
|
||||
IsReceiving() const
|
||||
{
|
||||
return GetDirectionAttribute().mValue & SdpDirectionAttribute::kRecvFlag;
|
||||
return GetDirectionAttribute().mValue & sdp::kRecv;
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsSending() const
|
||||
{
|
||||
return GetDirectionAttribute().mValue & SdpDirectionAttribute::kSendFlag;
|
||||
return GetDirectionAttribute().mValue & sdp::kSend;
|
||||
}
|
||||
|
||||
inline void
|
||||
SetReceiving(bool receiving)
|
||||
{
|
||||
auto direction = GetDirectionAttribute().mValue;
|
||||
if (direction & SdpDirectionAttribute::kSendFlag) {
|
||||
if (direction & sdp::kSend) {
|
||||
SetDirection(receiving ?
|
||||
SdpDirectionAttribute::kSendrecv :
|
||||
SdpDirectionAttribute::kSendonly);
|
||||
@ -132,7 +133,7 @@ public:
|
||||
SetSending(bool sending)
|
||||
{
|
||||
auto direction = GetDirectionAttribute().mValue;
|
||||
if (direction & SdpDirectionAttribute::kRecvFlag) {
|
||||
if (direction & sdp::kRecv) {
|
||||
SetDirection(sending ?
|
||||
SdpDirectionAttribute::kSendrecv :
|
||||
SdpDirectionAttribute::kRecvonly);
|
||||
@ -148,79 +149,24 @@ public:
|
||||
GetAttributeList().SetAttribute(new SdpDirectionAttribute(direction));
|
||||
}
|
||||
|
||||
const SdpFmtpAttributeList::Parameters*
|
||||
FindFmtp(const std::string& pt) const
|
||||
const SdpFmtpAttributeList::Parameters* FindFmtp(const std::string& pt) const;
|
||||
void SetFmtp(const SdpFmtpAttributeList::Fmtp& fmtp);
|
||||
const SdpRtpmapAttributeList::Rtpmap* FindRtpmap(const std::string& pt) const;
|
||||
const SdpSctpmapAttributeList::Sctpmap* FindSctpmap(
|
||||
const std::string& pt) const;
|
||||
bool HasRtcpFb(const std::string& pt,
|
||||
SdpRtcpFbAttributeList::Type type,
|
||||
const std::string& subType) const;
|
||||
SdpRtcpFbAttributeList GetRtcpFbs() const;
|
||||
void SetRtcpFbs(const SdpRtcpFbAttributeList& rtcpfbs);
|
||||
bool HasFormat(const std::string& format) const
|
||||
{
|
||||
const SdpAttributeList& attrs = GetAttributeList();
|
||||
|
||||
if (attrs.HasAttribute(SdpAttribute::kFmtpAttribute)) {
|
||||
const SdpFmtpAttributeList& fmtps = attrs.GetFmtp();
|
||||
for (auto i = fmtps.mFmtps.begin(); i != fmtps.mFmtps.end(); ++i) {
|
||||
if (i->format == pt && i->parameters) {
|
||||
return i->parameters.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return std::find(GetFormats().begin(), GetFormats().end(), format) !=
|
||||
GetFormats().end();
|
||||
}
|
||||
|
||||
const SdpRtpmapAttributeList::Rtpmap*
|
||||
FindRtpmap(const std::string& pt) const
|
||||
{
|
||||
auto& attrs = GetAttributeList();
|
||||
if (!attrs.HasAttribute(SdpAttribute::kRtpmapAttribute)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SdpRtpmapAttributeList& rtpmap = attrs.GetRtpmap();
|
||||
if (!rtpmap.HasEntry(pt)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &rtpmap.GetEntry(pt);
|
||||
}
|
||||
|
||||
const SdpSctpmapAttributeList::Sctpmap*
|
||||
FindSctpmap(const std::string& pt) const
|
||||
{
|
||||
auto& attrs = GetAttributeList();
|
||||
if (!attrs.HasAttribute(SdpAttribute::kSctpmapAttribute)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const SdpSctpmapAttributeList& sctpmap = attrs.GetSctpmap();
|
||||
if (!sctpmap.HasEntry(pt)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &sctpmap.GetEntry(pt);
|
||||
}
|
||||
|
||||
bool
|
||||
HasRtcpFb(const std::string& pt,
|
||||
SdpRtcpFbAttributeList::Type type,
|
||||
const std::string& subType) const
|
||||
{
|
||||
const SdpAttributeList& attrs(GetAttributeList());
|
||||
|
||||
if (!attrs.HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& rtcpfb : attrs.GetRtcpFb().mFeedbacks) {
|
||||
if (rtcpfb.type == type) {
|
||||
if (rtcpfb.pt == "*" || rtcpfb.pt == pt) {
|
||||
if (rtcpfb.parameter == subType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SetSsrcs(const std::vector<uint32_t>& ssrcs,
|
||||
const std::string& cname);
|
||||
void AddMsid(const std::string& id, const std::string& appdata);
|
||||
|
||||
private:
|
||||
size_t mLevel;
|
||||
|
@ -127,7 +127,10 @@ SipccSdpMediaSection::Load(sdp_t* sdp, uint16_t level,
|
||||
if (!LoadProtocol(sdp, level, errorHolder)) {
|
||||
return false;
|
||||
}
|
||||
LoadFormats(sdp, level);
|
||||
|
||||
if (!LoadFormats(sdp, level, errorHolder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mAttributeList.Load(sdp, level, errorHolder)) {
|
||||
return false;
|
||||
@ -181,8 +184,10 @@ SipccSdpMediaSection::LoadProtocol(sdp_t* sdp, uint16_t level,
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SipccSdpMediaSection::LoadFormats(sdp_t* sdp, uint16_t level)
|
||||
bool
|
||||
SipccSdpMediaSection::LoadFormats(sdp_t* sdp,
|
||||
uint16_t level,
|
||||
SdpErrorHolder& errorHolder)
|
||||
{
|
||||
sdp_media_e mtype = sdp_get_media_type(sdp, level);
|
||||
|
||||
@ -198,6 +203,12 @@ SipccSdpMediaSection::LoadFormats(sdp_t* sdp, uint16_t level)
|
||||
uint32_t ptype =
|
||||
sdp_get_media_payload_type(sdp, level, i + 1, &indicator);
|
||||
|
||||
if (GET_DYN_PAYLOAD_TYPE_VALUE(ptype) > UINT8_MAX) {
|
||||
errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
|
||||
"Format is too large");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ostringstream osPayloadType;
|
||||
// sipcc stores payload types in a funny way. When sipcc and the SDP it
|
||||
// parsed differ on what payload type number should be used for a given
|
||||
@ -208,6 +219,8 @@ SipccSdpMediaSection::LoadFormats(sdp_t* sdp, uint16_t level)
|
||||
mFormats.push_back(osPayloadType.str());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -75,7 +75,7 @@ private:
|
||||
bool Load(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
|
||||
bool LoadConnection(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
|
||||
bool LoadProtocol(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
|
||||
void LoadFormats(sdp_t* sdp, uint16_t level);
|
||||
bool LoadFormats(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
|
||||
|
||||
// the following values are cached on first get
|
||||
MediaType mMediaType;
|
||||
|
@ -838,22 +838,7 @@ protected:
|
||||
UniquePtr<Sdp> parsed(Parse(*sdp));
|
||||
ASSERT_TRUE(parsed.get());
|
||||
ASSERT_LT(level, parsed->GetMediaSectionCount());
|
||||
parsed->GetMediaSection(level).SetPort(0);
|
||||
|
||||
auto& attrs = parsed->GetMediaSection(level).GetAttributeList();
|
||||
|
||||
ASSERT_TRUE(attrs.HasAttribute(SdpAttribute::kMidAttribute));
|
||||
std::string mid = attrs.GetMid();
|
||||
|
||||
attrs.Clear();
|
||||
|
||||
ASSERT_TRUE(
|
||||
parsed->GetAttributeList().HasAttribute(SdpAttribute::kGroupAttribute));
|
||||
|
||||
SdpGroupAttributeList* newGroupAttr(new SdpGroupAttributeList(
|
||||
parsed->GetAttributeList().GetGroup()));
|
||||
newGroupAttr->RemoveMid(mid);
|
||||
parsed->GetAttributeList().SetAttribute(newGroupAttr);
|
||||
SdpHelper::DisableMsection(parsed.get(), &parsed->GetMediaSection(level));
|
||||
(*sdp) = parsed->ToString();
|
||||
}
|
||||
|
||||
@ -861,13 +846,11 @@ protected:
|
||||
DumpTrack(const JsepTrack& track)
|
||||
{
|
||||
std::cerr << " type=" << track.GetMediaType() << std::endl;
|
||||
std::cerr << " protocol=" << track.GetNegotiatedDetails()->GetProtocol()
|
||||
<< std::endl;
|
||||
std::cerr << " codecs=" << std::endl;
|
||||
size_t num_codecs = track.GetNegotiatedDetails()->GetCodecCount();
|
||||
for (size_t i = 0; i < num_codecs; ++i) {
|
||||
const JsepCodecDescription* codec;
|
||||
ASSERT_EQ(NS_OK, track.GetNegotiatedDetails()->GetCodec(i, &codec));
|
||||
const JsepCodecDescription* codec =
|
||||
track.GetNegotiatedDetails()->GetCodec(i);
|
||||
std::cerr << " " << codec->mName << std::endl;
|
||||
}
|
||||
}
|
||||
@ -2652,50 +2635,50 @@ TEST_F(JsepSessionTest, ValidateOfferedCodecParams)
|
||||
ASSERT_EQ(4U, fmtps.size());
|
||||
|
||||
// VP8
|
||||
ASSERT_EQ("120", fmtps[0].format);
|
||||
ASSERT_TRUE(!!fmtps[0].parameters);
|
||||
ASSERT_EQ(SdpRtpmapAttributeList::kVP8, fmtps[0].parameters->codec_type);
|
||||
const SdpFmtpAttributeList::Parameters* vp8_params =
|
||||
video_section.FindFmtp("120");
|
||||
ASSERT_TRUE(vp8_params);
|
||||
ASSERT_EQ(SdpRtpmapAttributeList::kVP8, vp8_params->codec_type);
|
||||
|
||||
auto& parsed_vp8_params =
|
||||
*static_cast<const SdpFmtpAttributeList::VP8Parameters*>(
|
||||
fmtps[0].parameters.get());
|
||||
*static_cast<const SdpFmtpAttributeList::VP8Parameters*>(vp8_params);
|
||||
|
||||
ASSERT_EQ((uint32_t)12288, parsed_vp8_params.max_fs);
|
||||
ASSERT_EQ((uint32_t)60, parsed_vp8_params.max_fr);
|
||||
|
||||
// VP9
|
||||
ASSERT_EQ("121", fmtps[1].format);
|
||||
ASSERT_TRUE(!!fmtps[1].parameters);
|
||||
ASSERT_EQ(SdpRtpmapAttributeList::kVP9, fmtps[1].parameters->codec_type);
|
||||
const SdpFmtpAttributeList::Parameters* vp9_params =
|
||||
video_section.FindFmtp("121");
|
||||
ASSERT_TRUE(vp9_params);
|
||||
ASSERT_EQ(SdpRtpmapAttributeList::kVP9, vp9_params->codec_type);
|
||||
|
||||
auto& parsed_vp9_params =
|
||||
*static_cast<const SdpFmtpAttributeList::VP8Parameters*>(
|
||||
fmtps[1].parameters.get());
|
||||
*static_cast<const SdpFmtpAttributeList::VP8Parameters*>(vp9_params);
|
||||
|
||||
ASSERT_EQ((uint32_t)12288, parsed_vp9_params.max_fs);
|
||||
ASSERT_EQ((uint32_t)60, parsed_vp9_params.max_fr);
|
||||
|
||||
// H264 packetization mode 1
|
||||
ASSERT_EQ("126", fmtps[2].format);
|
||||
ASSERT_TRUE(!!fmtps[2].parameters);
|
||||
ASSERT_EQ(SdpRtpmapAttributeList::kH264, fmtps[2].parameters->codec_type);
|
||||
const SdpFmtpAttributeList::Parameters* h264_1_params =
|
||||
video_section.FindFmtp("126");
|
||||
ASSERT_TRUE(h264_1_params);
|
||||
ASSERT_EQ(SdpRtpmapAttributeList::kH264, h264_1_params->codec_type);
|
||||
|
||||
auto& parsed_h264_1_params =
|
||||
*static_cast<const SdpFmtpAttributeList::H264Parameters*>(
|
||||
fmtps[2].parameters.get());
|
||||
*static_cast<const SdpFmtpAttributeList::H264Parameters*>(h264_1_params);
|
||||
|
||||
ASSERT_EQ((uint32_t)0x42e00d, parsed_h264_1_params.profile_level_id);
|
||||
ASSERT_TRUE(parsed_h264_1_params.level_asymmetry_allowed);
|
||||
ASSERT_EQ(1U, parsed_h264_1_params.packetization_mode);
|
||||
|
||||
// H264 packetization mode 0
|
||||
ASSERT_EQ("97", fmtps[3].format);
|
||||
ASSERT_TRUE(!!fmtps[3].parameters);
|
||||
ASSERT_EQ(SdpRtpmapAttributeList::kH264, fmtps[3].parameters->codec_type);
|
||||
const SdpFmtpAttributeList::Parameters* h264_0_params =
|
||||
video_section.FindFmtp("97");
|
||||
ASSERT_TRUE(h264_0_params);
|
||||
ASSERT_EQ(SdpRtpmapAttributeList::kH264, h264_0_params->codec_type);
|
||||
|
||||
auto& parsed_h264_0_params =
|
||||
*static_cast<const SdpFmtpAttributeList::H264Parameters*>(
|
||||
fmtps[3].parameters.get());
|
||||
*static_cast<const SdpFmtpAttributeList::H264Parameters*>(h264_0_params);
|
||||
|
||||
ASSERT_EQ((uint32_t)0x42e00d, parsed_h264_0_params.profile_level_id);
|
||||
ASSERT_TRUE(parsed_h264_0_params.level_asymmetry_allowed);
|
||||
@ -2808,16 +2791,6 @@ TEST_F(JsepSessionTest, ValidateAnsweredCodecParams)
|
||||
offerPairs[1].mSending->GetNegotiatedDetails()->GetCodecCount());
|
||||
ASSERT_EQ(1U,
|
||||
offerPairs[1].mReceiving->GetNegotiatedDetails()->GetCodecCount());
|
||||
const JsepCodecDescription* offerRecvCodec;
|
||||
ASSERT_EQ(NS_OK,
|
||||
offerPairs[1].mReceiving->GetNegotiatedDetails()->GetCodec(
|
||||
0,
|
||||
&offerRecvCodec));
|
||||
const JsepCodecDescription* offerSendCodec;
|
||||
ASSERT_EQ(NS_OK,
|
||||
offerPairs[1].mSending->GetNegotiatedDetails()->GetCodec(
|
||||
0,
|
||||
&offerSendCodec));
|
||||
|
||||
auto answerPairs = mSessionAns.GetNegotiatedTrackPairs();
|
||||
ASSERT_EQ(2U, answerPairs.size());
|
||||
@ -2829,16 +2802,6 @@ TEST_F(JsepSessionTest, ValidateAnsweredCodecParams)
|
||||
answerPairs[1].mSending->GetNegotiatedDetails()->GetCodecCount());
|
||||
ASSERT_EQ(1U,
|
||||
answerPairs[1].mReceiving->GetNegotiatedDetails()->GetCodecCount());
|
||||
const JsepCodecDescription* answerRecvCodec;
|
||||
ASSERT_EQ(NS_OK,
|
||||
answerPairs[1].mReceiving->GetNegotiatedDetails()->GetCodec(
|
||||
0,
|
||||
&answerRecvCodec));
|
||||
const JsepCodecDescription* answerSendCodec;
|
||||
ASSERT_EQ(NS_OK,
|
||||
answerPairs[1].mSending->GetNegotiatedDetails()->GetCodec(
|
||||
0,
|
||||
&answerSendCodec));
|
||||
|
||||
#if 0
|
||||
// H264 packetization mode 1
|
||||
@ -2888,16 +2851,10 @@ static void ReplaceAll(const std::string& toReplace,
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kSending,
|
||||
kReceiving
|
||||
} Direction;
|
||||
|
||||
static void
|
||||
GetCodec(JsepSession& session,
|
||||
size_t pairIndex,
|
||||
Direction direction,
|
||||
sdp::Direction direction,
|
||||
size_t codecIndex,
|
||||
const JsepCodecDescription** codecOut)
|
||||
{
|
||||
@ -2905,12 +2862,11 @@ GetCodec(JsepSession& session,
|
||||
ASSERT_LT(pairIndex, session.GetNegotiatedTrackPairs().size());
|
||||
JsepTrackPair pair(session.GetNegotiatedTrackPairs().front());
|
||||
RefPtr<JsepTrack> track(
|
||||
(direction == kSending) ? pair.mSending : pair.mReceiving);
|
||||
(direction == sdp::kSend) ? pair.mSending : pair.mReceiving);
|
||||
ASSERT_TRUE(track);
|
||||
ASSERT_TRUE(track->GetNegotiatedDetails());
|
||||
ASSERT_LT(codecIndex, track->GetNegotiatedDetails()->GetCodecCount());
|
||||
ASSERT_EQ(NS_OK,
|
||||
track->GetNegotiatedDetails()->GetCodec(codecIndex, codecOut));
|
||||
*codecOut = track->GetNegotiatedDetails()->GetCodec(codecIndex);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2945,7 +2901,7 @@ TEST_F(JsepSessionTest, TestH264Negotiation)
|
||||
SetLocalAnswer(answer, CHECK_SUCCESS);
|
||||
|
||||
const JsepCodecDescription* offererSendCodec;
|
||||
GetCodec(mSessionOff, 0, kSending, 0, &offererSendCodec);
|
||||
GetCodec(mSessionOff, 0, sdp::kSend, 0, &offererSendCodec);
|
||||
ASSERT_TRUE(offererSendCodec);
|
||||
ASSERT_EQ("H264", offererSendCodec->mName);
|
||||
const JsepVideoCodecDescription* offererVideoSendCodec(
|
||||
@ -2953,14 +2909,14 @@ TEST_F(JsepSessionTest, TestH264Negotiation)
|
||||
ASSERT_EQ((uint32_t)0x42e00d, offererVideoSendCodec->mProfileLevelId);
|
||||
|
||||
const JsepCodecDescription* offererRecvCodec;
|
||||
GetCodec(mSessionOff, 0, kReceiving, 0, &offererRecvCodec);
|
||||
GetCodec(mSessionOff, 0, sdp::kRecv, 0, &offererRecvCodec);
|
||||
ASSERT_EQ("H264", offererRecvCodec->mName);
|
||||
const JsepVideoCodecDescription* offererVideoRecvCodec(
|
||||
static_cast<const JsepVideoCodecDescription*>(offererRecvCodec));
|
||||
ASSERT_EQ((uint32_t)0x42e00b, offererVideoRecvCodec->mProfileLevelId);
|
||||
|
||||
const JsepCodecDescription* answererSendCodec;
|
||||
GetCodec(mSessionAns, 0, kSending, 0, &answererSendCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kSend, 0, &answererSendCodec);
|
||||
ASSERT_TRUE(answererSendCodec);
|
||||
ASSERT_EQ("H264", answererSendCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoSendCodec(
|
||||
@ -2968,7 +2924,7 @@ TEST_F(JsepSessionTest, TestH264Negotiation)
|
||||
ASSERT_EQ((uint32_t)0x42e00b, answererVideoSendCodec->mProfileLevelId);
|
||||
|
||||
const JsepCodecDescription* answererRecvCodec;
|
||||
GetCodec(mSessionAns, 0, kReceiving, 0, &answererRecvCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kRecv, 0, &answererRecvCodec);
|
||||
ASSERT_EQ("H264", answererRecvCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoRecvCodec(
|
||||
static_cast<const JsepVideoCodecDescription*>(answererRecvCodec));
|
||||
@ -3018,7 +2974,7 @@ TEST_F(JsepSessionTest, TestH264NegotiationOffererDefault)
|
||||
SetLocalAnswer(answer, CHECK_SUCCESS);
|
||||
|
||||
const JsepCodecDescription* answererSendCodec;
|
||||
GetCodec(mSessionAns, 0, kSending, 0, &answererSendCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kSend, 0, &answererSendCodec);
|
||||
ASSERT_TRUE(answererSendCodec);
|
||||
ASSERT_EQ("H264", answererSendCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoSendCodec(
|
||||
@ -3046,7 +3002,7 @@ TEST_F(JsepSessionTest, TestH264NegotiationOffererNoFmtp)
|
||||
SetLocalAnswer(answer, CHECK_SUCCESS);
|
||||
|
||||
const JsepCodecDescription* answererSendCodec;
|
||||
GetCodec(mSessionAns, 0, kSending, 0, &answererSendCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kSend, 0, &answererSendCodec);
|
||||
ASSERT_TRUE(answererSendCodec);
|
||||
ASSERT_EQ("H264", answererSendCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoSendCodec(
|
||||
@ -3054,7 +3010,7 @@ TEST_F(JsepSessionTest, TestH264NegotiationOffererNoFmtp)
|
||||
ASSERT_EQ((uint32_t)0x420010, answererVideoSendCodec->mProfileLevelId);
|
||||
|
||||
const JsepCodecDescription* answererRecvCodec;
|
||||
GetCodec(mSessionAns, 0, kReceiving, 0, &answererRecvCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kRecv, 0, &answererRecvCodec);
|
||||
ASSERT_EQ("H264", answererRecvCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoRecvCodec(
|
||||
static_cast<const JsepVideoCodecDescription*>(answererRecvCodec));
|
||||
@ -3086,7 +3042,7 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByOffererWithLowLevel)
|
||||
// behave normally, and we test the normal behavior elsewhere.
|
||||
|
||||
const JsepCodecDescription* answererSendCodec;
|
||||
GetCodec(mSessionAns, 0, kSending, 0, &answererSendCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kSend, 0, &answererSendCodec);
|
||||
ASSERT_TRUE(answererSendCodec);
|
||||
ASSERT_EQ("H264", answererSendCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoSendCodec(
|
||||
@ -3094,7 +3050,7 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByOffererWithLowLevel)
|
||||
ASSERT_EQ((uint32_t)0x42e00b, answererVideoSendCodec->mProfileLevelId);
|
||||
|
||||
const JsepCodecDescription* answererRecvCodec;
|
||||
GetCodec(mSessionAns, 0, kReceiving, 0, &answererRecvCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kRecv, 0, &answererRecvCodec);
|
||||
ASSERT_EQ("H264", answererRecvCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoRecvCodec(
|
||||
static_cast<const JsepVideoCodecDescription*>(answererRecvCodec));
|
||||
@ -3126,7 +3082,7 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByOffererWithHighLevel)
|
||||
// behave normally, and we test the normal behavior elsewhere.
|
||||
|
||||
const JsepCodecDescription* answererSendCodec;
|
||||
GetCodec(mSessionAns, 0, kSending, 0, &answererSendCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kSend, 0, &answererSendCodec);
|
||||
ASSERT_TRUE(answererSendCodec);
|
||||
ASSERT_EQ("H264", answererSendCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoSendCodec(
|
||||
@ -3134,7 +3090,7 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByOffererWithHighLevel)
|
||||
ASSERT_EQ((uint32_t)0x42e00b, answererVideoSendCodec->mProfileLevelId);
|
||||
|
||||
const JsepCodecDescription* answererRecvCodec;
|
||||
GetCodec(mSessionAns, 0, kReceiving, 0, &answererRecvCodec);
|
||||
GetCodec(mSessionAns, 0, sdp::kRecv, 0, &answererRecvCodec);
|
||||
ASSERT_EQ("H264", answererRecvCodec->mName);
|
||||
const JsepVideoCodecDescription* answererVideoRecvCodec(
|
||||
static_cast<const JsepVideoCodecDescription*>(answererRecvCodec));
|
||||
@ -3162,7 +3118,7 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByAnswererWithLowLevel)
|
||||
SetLocalAnswer(answer, CHECK_SUCCESS);
|
||||
|
||||
const JsepCodecDescription* offererSendCodec;
|
||||
GetCodec(mSessionOff, 0, kSending, 0, &offererSendCodec);
|
||||
GetCodec(mSessionOff, 0, sdp::kSend, 0, &offererSendCodec);
|
||||
ASSERT_TRUE(offererSendCodec);
|
||||
ASSERT_EQ("H264", offererSendCodec->mName);
|
||||
const JsepVideoCodecDescription* offererVideoSendCodec(
|
||||
@ -3170,7 +3126,7 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByAnswererWithLowLevel)
|
||||
ASSERT_EQ((uint32_t)0x42e00b, offererVideoSendCodec->mProfileLevelId);
|
||||
|
||||
const JsepCodecDescription* offererRecvCodec;
|
||||
GetCodec(mSessionOff, 0, kReceiving, 0, &offererRecvCodec);
|
||||
GetCodec(mSessionOff, 0, sdp::kRecv, 0, &offererRecvCodec);
|
||||
ASSERT_EQ("H264", offererRecvCodec->mName);
|
||||
const JsepVideoCodecDescription* offererVideoRecvCodec(
|
||||
static_cast<const JsepVideoCodecDescription*>(offererRecvCodec));
|
||||
@ -3202,7 +3158,7 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByAnswererWithHighLevel)
|
||||
SetLocalAnswer(answer, CHECK_SUCCESS);
|
||||
|
||||
const JsepCodecDescription* offererSendCodec;
|
||||
GetCodec(mSessionOff, 0, kSending, 0, &offererSendCodec);
|
||||
GetCodec(mSessionOff, 0, sdp::kSend, 0, &offererSendCodec);
|
||||
ASSERT_TRUE(offererSendCodec);
|
||||
ASSERT_EQ("H264", offererSendCodec->mName);
|
||||
const JsepVideoCodecDescription* offererVideoSendCodec(
|
||||
@ -3210,7 +3166,7 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByAnswererWithHighLevel)
|
||||
ASSERT_EQ((uint32_t)0x42e00b, offererVideoSendCodec->mProfileLevelId);
|
||||
|
||||
const JsepCodecDescription* offererRecvCodec;
|
||||
GetCodec(mSessionOff, 0, kReceiving, 0, &offererRecvCodec);
|
||||
GetCodec(mSessionOff, 0, sdp::kRecv, 0, &offererRecvCodec);
|
||||
ASSERT_EQ("H264", offererRecvCodec->mName);
|
||||
const JsepVideoCodecDescription* offererVideoRecvCodec(
|
||||
static_cast<const JsepVideoCodecDescription*>(offererRecvCodec));
|
||||
@ -3223,8 +3179,9 @@ TEST_F(JsepSessionTest, TestH264LevelAsymmetryDisallowedByAnswererWithHighLevel)
|
||||
|
||||
TEST_P(JsepSessionTest, TestRejectMline)
|
||||
{
|
||||
AddTracks(mSessionOff);
|
||||
AddTracks(mSessionAns);
|
||||
// We need to do this before adding tracks
|
||||
types = BuildTypes(GetParam());
|
||||
std::sort(types.begin(), types.end());
|
||||
|
||||
switch (types.front()) {
|
||||
case SdpMediaSection::kAudio:
|
||||
@ -3243,6 +3200,9 @@ TEST_P(JsepSessionTest, TestRejectMline)
|
||||
ASSERT_TRUE(false) << "Unknown media type";
|
||||
}
|
||||
|
||||
AddTracks(mSessionOff);
|
||||
AddTracks(mSessionAns);
|
||||
|
||||
std::string offer = CreateOffer();
|
||||
mSessionOff.SetLocalDescription(kJsepSdpOffer, offer);
|
||||
mSessionAns.SetRemoteDescription(kJsepSdpOffer, offer);
|
||||
@ -3399,8 +3359,7 @@ TEST_F(JsepSessionTest, TestRtcpFbStar)
|
||||
ASSERT_TRUE(track->GetNegotiatedDetails());
|
||||
auto* details = track->GetNegotiatedDetails();
|
||||
for (size_t i = 0; i < details->GetCodecCount(); ++i) {
|
||||
const JsepCodecDescription* codec;
|
||||
ASSERT_EQ(NS_OK, details->GetCodec(i, &codec));
|
||||
const JsepCodecDescription* codec = details->GetCodec(i);
|
||||
const JsepVideoCodecDescription* videoCodec =
|
||||
static_cast<const JsepVideoCodecDescription*>(codec);
|
||||
ASSERT_EQ(1U, videoCodec->mNackFbTypes.size());
|
||||
@ -3535,10 +3494,10 @@ TEST_F(JsepSessionTest, StronglyPreferredCodec)
|
||||
OfferAnswer();
|
||||
|
||||
const JsepCodecDescription* codec;
|
||||
GetCodec(mSessionAns, 0, kSending, 0, &codec);
|
||||
GetCodec(mSessionAns, 0, sdp::kSend, 0, &codec);
|
||||
ASSERT_TRUE(codec);
|
||||
ASSERT_EQ("H264", codec->mName);
|
||||
GetCodec(mSessionAns, 0, kReceiving, 0, &codec);
|
||||
GetCodec(mSessionAns, 0, sdp::kRecv, 0, &codec);
|
||||
ASSERT_TRUE(codec);
|
||||
ASSERT_EQ("H264", codec->mName);
|
||||
}
|
||||
@ -3552,11 +3511,11 @@ TEST_F(JsepSessionTest, LowDynamicPayloadType)
|
||||
|
||||
OfferAnswer();
|
||||
const JsepCodecDescription* codec;
|
||||
GetCodec(mSessionAns, 0, kSending, 0, &codec);
|
||||
GetCodec(mSessionAns, 0, sdp::kSend, 0, &codec);
|
||||
ASSERT_TRUE(codec);
|
||||
ASSERT_EQ("opus", codec->mName);
|
||||
ASSERT_EQ("12", codec->mDefaultPt);
|
||||
GetCodec(mSessionAns, 0, kReceiving, 0, &codec);
|
||||
GetCodec(mSessionAns, 0, sdp::kRecv, 0, &codec);
|
||||
ASSERT_TRUE(codec);
|
||||
ASSERT_EQ("opus", codec->mName);
|
||||
ASSERT_EQ("12", codec->mDefaultPt);
|
||||
@ -3574,11 +3533,11 @@ TEST_F(JsepSessionTest, PayloadTypeClash)
|
||||
|
||||
OfferAnswer();
|
||||
const JsepCodecDescription* codec;
|
||||
GetCodec(mSessionAns, 0, kSending, 0, &codec);
|
||||
GetCodec(mSessionAns, 0, sdp::kSend, 0, &codec);
|
||||
ASSERT_TRUE(codec);
|
||||
ASSERT_EQ("opus", codec->mName);
|
||||
ASSERT_EQ("0", codec->mDefaultPt);
|
||||
GetCodec(mSessionAns, 0, kReceiving, 0, &codec);
|
||||
GetCodec(mSessionAns, 0, sdp::kRecv, 0, &codec);
|
||||
ASSERT_TRUE(codec);
|
||||
ASSERT_EQ("opus", codec->mName);
|
||||
ASSERT_EQ("0", codec->mDefaultPt);
|
||||
|
Loading…
Reference in New Issue
Block a user