Bug 1095218 - Part 1: msid support. r=mt

--HG--
extra : rebase_source : 85f8a97d16496f2b00ea049ebe29d41becd15a62
This commit is contained in:
Byron Campen [:bwc] 2014-12-01 21:19:57 -08:00
parent 7f1b16e03a
commit d02c39d11f
16 changed files with 467 additions and 46 deletions

View File

@ -32,15 +32,10 @@ function theTest() {
});
test.setMediaConstraints([{
audio: true,
peerIdentity: id2
}, {
video: true,
peerIdentity: id2
}], [{
audio: true,
fake: true,
peerIdentity: id1
}, {
video: true,
fake: true,
peerIdentity: id1

View File

@ -236,6 +236,9 @@ JsepSessionImpl::AddOfferMSectionsByType(SdpMediaSection::MediaType mediatype,
AddLocalSsrcs(*track->mTrack,
&sdp->GetMediaSection(*track->mAssignedMLine));
AddLocalIds(*track->mTrack,
&sdp->GetMediaSection(*track->mAssignedMLine));
}
while (offerToReceive.isSome() && added < *offerToReceive) {
@ -268,6 +271,133 @@ JsepSessionImpl::SetupBundle(Sdp* sdp) const
}
}
void
JsepSessionImpl::SetupMsidSemantic(const std::vector<std::string>& msids,
Sdp* sdp) const
{
if (!msids.empty()) {
UniquePtr<SdpMsidSemanticAttributeList> msidSemantics(
new SdpMsidSemanticAttributeList);
msidSemantics->PushEntry("WMS", msids);
sdp->GetAttributeList().SetAttribute(msidSemantics.release());
}
}
nsresult
JsepSessionImpl::GetIdsFromMsid(const Sdp& sdp,
const SdpMediaSection& msection,
std::string* streamId,
std::string* trackId)
{
if (!sdp.GetAttributeList().HasAttribute(
SdpAttribute::kMsidSemanticAttribute)) {
return NS_ERROR_NOT_AVAILABLE;
}
auto& msidSemantics = sdp.GetAttributeList().GetMsidSemantic().mMsidSemantics;
std::vector<SdpMsidAttributeList::Msid> allMsids;
nsresult rv = GetMsids(msection, &allMsids);
NS_ENSURE_SUCCESS(rv, rv);
bool allMsidsAreWebrtc = false;
std::set<std::string> webrtcMsids;
for (auto i = msidSemantics.begin(); i != msidSemantics.end(); ++i) {
if (i->semantic == "WMS") {
for (auto j = i->msids.begin(); j != i->msids.end(); ++j) {
if (*j == "*") {
allMsidsAreWebrtc = true;
} else {
webrtcMsids.insert(*j);
}
}
break;
}
}
bool found = false;
for (auto i = allMsids.begin(); i != allMsids.end(); ++i) {
if (allMsidsAreWebrtc || webrtcMsids.count(i->identifier)) {
// For now, we assume that there is exactly one streamId/trackId pair
// per m-section. Later on, we'll add handling for multiple remote tracks
// per m-section.
if (!found) {
*streamId = i->identifier;
*trackId = i->appdata;
found = true;
} else if ((*streamId != i->identifier) || (*trackId != i->appdata)) {
// Bail if there are multiple stream/track ids for now
JSEP_SET_ERROR("Found multiple different webrtc msids in m-section "
<< msection.GetLevel() << ". The behavior here is "
"undefined.");
return NS_ERROR_INVALID_ARG;
}
}
}
if (!found) {
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
nsresult
JsepSessionImpl::GetMsids(
const SdpMediaSection& msection,
std::vector<SdpMsidAttributeList::Msid>* msids)
{
if (msection.GetAttributeList().HasAttribute(SdpAttribute::kMsidAttribute)) {
*msids = msection.GetAttributeList().GetMsid().mMsids;
}
// Can we find some additional msids in ssrc attributes?
// (Chrome does not put plain-old msid attributes in its SDP)
if (msection.GetAttributeList().HasAttribute(SdpAttribute::kSsrcAttribute)) {
auto& ssrcs = msection.GetAttributeList().GetSsrc().mSsrcs;
for (auto i = ssrcs.begin(); i != ssrcs.end(); ++i) {
if (i->attribute.find("msid:") == 0) {
// Would be nice if SdpSsrcAttributeList could parse out the contained
// attribute, but at least the parse here is simple.
size_t streamIdStart = i->attribute.find_first_not_of(" \t", 5);
// We do not assume the appdata token is here, since this is not
// necessarily a webrtc msid
if (streamIdStart == std::string::npos) {
JSEP_SET_ERROR("Malformed source-level msid attribute: "
<< i->attribute);
return NS_ERROR_INVALID_ARG;
}
size_t streamIdEnd = i->attribute.find_first_of(" \t", streamIdStart);
if (streamIdEnd == std::string::npos) {
streamIdEnd = i->attribute.size();
}
size_t trackIdStart =
i->attribute.find_first_not_of(" \t", streamIdEnd);
if (trackIdStart == std::string::npos) {
trackIdStart = i->attribute.size();
}
size_t trackIdEnd = i->attribute.find_first_of(" \t", trackIdStart);
if (trackIdEnd == std::string::npos) {
trackIdEnd = i->attribute.size();
}
size_t streamIdSize = streamIdEnd - streamIdStart;
size_t trackIdSize = trackIdEnd - trackIdStart;
msids->push_back({i->attribute.substr(streamIdStart, streamIdSize),
i->attribute.substr(trackIdStart, trackIdSize)});
}
}
}
return NS_OK;
}
nsresult
JsepSessionImpl::CreateOffer(const JsepOfferOptions& options,
std::string* offer)
@ -395,6 +525,24 @@ JsepSessionImpl::AddLocalSsrcs(const JsepTrack& track,
}
}
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
@ -663,6 +811,8 @@ JsepSessionImpl::CreateAnswerMSection(const JsepAnswerOptions& options,
AddLocalSsrcs(*track->mTrack, msection);
AddLocalIds(*track->mTrack, msection);
localDirection = SdpDirectionAttribute::kSendonly;
track->mAssignedMLine = Some(mlineIndex);
found = true;
@ -1462,7 +1612,7 @@ JsepSessionImpl::SetRemoteTracksFromDescription(const Sdp& remoteDescription)
// TODO(bug 1017888): Suppress new track creation on renegotiation
// of existing tracks.
if (direction & SdpDirectionAttribute::kSendFlag) {
nsresult rv = CreateReceivingTrack(i, msection);
nsresult rv = CreateReceivingTrack(i, remoteDescription, msection);
NS_ENSURE_SUCCESS(rv, rv);
}
}
@ -1521,20 +1671,31 @@ JsepSessionImpl::ValidateLocalDescription(const Sdp& description)
nsresult
JsepSessionImpl::CreateReceivingTrack(size_t mline,
const Sdp& sdp,
const SdpMediaSection& msection)
{
std::string streamId;
std::string trackId;
// Generate random track ids.
// TODO(bug 1095218): Pull track and stream IDs out of SDP if available.
if (!mUuidGen->Generate(&trackId)) {
JSEP_SET_ERROR("Failed to generate UUID for JsepTrack");
return NS_ERROR_FAILURE;
nsresult rv = GetIdsFromMsid(sdp, msection, &streamId, &trackId);
if (NS_FAILED(rv)) {
if (rv != NS_ERROR_NOT_AVAILABLE) {
// Malformed ssrc attribute, probably
return rv;
}
streamId = mDefaultRemoteStreamId;
// Generate random track ids.
if (!mUuidGen->Generate(&trackId)) {
JSEP_SET_ERROR("Failed to generate UUID for JsepTrack");
return NS_ERROR_FAILURE;
}
}
JsepTrack* remote = new JsepTrack(msection.GetMediaType(),
mDefaultRemoteStreamId,
streamId,
trackId,
JsepTrack::kJsepTrackReceiving);
@ -1590,6 +1751,12 @@ JsepSessionImpl::CreateGenericSDP(UniquePtr<Sdp>* sdpp)
iceOpts->PushEntry("trickle");
sdp->GetAttributeList().SetAttribute(iceOpts);
// This assumes content doesn't add a bunch of msid attributes with a
// different semantic in mind.
std::vector<std::string> msids;
msids.push_back("*");
SetupMsidSemantic(msids, sdp.get());
*sdpp = Move(sdp);
return NS_OK;
}

View File

@ -210,6 +210,7 @@ private:
void AddExtmap(SdpMediaSection* msection) const;
void AddMid(const std::string& mid, SdpMediaSection* msection) const;
void AddLocalSsrcs(const JsepTrack& track, SdpMediaSection* msection) const;
void AddLocalIds(const JsepTrack& track, SdpMediaSection* msection) const;
JsepCodecDescription* FindMatchingCodec(
const std::string& pt,
const SdpMediaSection& msection) const;
@ -231,7 +232,9 @@ private:
nsresult ValidateLocalDescription(const Sdp& description);
nsresult SetRemoteTracksFromDescription(const Sdp& remoteDescription);
// Non-const because we use our Uuid generator
nsresult CreateReceivingTrack(size_t mline, const SdpMediaSection& msection);
nsresult CreateReceivingTrack(size_t mline,
const Sdp& sdp,
const SdpMediaSection& msection);
nsresult HandleNegotiatedSession(const UniquePtr<Sdp>& local,
const UniquePtr<Sdp>& remote);
nsresult DetermineSendingDirection(SdpDirectionAttribute::Direction offer,
@ -244,6 +247,13 @@ private:
Maybe<size_t> offerToReceive,
Sdp* sdp);
void SetupBundle(Sdp* sdp) const;
void SetupMsidSemantic(const std::vector<std::string>& msids, Sdp* sdp) const;
nsresult GetIdsFromMsid(const Sdp& sdp,
const SdpMediaSection& msection,
std::string* streamId,
std::string* trackId);
nsresult GetMsids(const SdpMediaSection& msection,
std::vector<SdpMsidAttributeList::Msid>* msids);
nsresult CreateOfferMSection(SdpMediaSection::MediaType type,
SdpDirectionAttribute::Direction direction,
SdpMediaSection::Protocol proto,

View File

@ -200,12 +200,14 @@ public:
for (uint32_t i = 0; i < tracks.Length(); i++) {
JSErrorResult rv;
mObserver->OnAddTrack(*tracks[i], rv);
CSFLogInfo(logTag, "Calling OnAddTrack");
if (rv.Failed()) {
CSFLogError(logTag, ": OnAddTrack(%d) failed! Error: %u", i,
static_cast<uint32_t>(rv.ErrorCode()));
}
}
JSErrorResult rv;
CSFLogInfo(logTag, "Calling OnAddStream");
mObserver->OnAddStream(*aStream, rv);
if (rv.Failed()) {
CSFLogError(logTag, ": OnAddStream() failed! Error: %u", static_cast<uint32_t>(rv.ErrorCode()));

View File

@ -164,6 +164,18 @@ SdpMsidAttributeList::Serialize(std::ostream& os) const
}
}
void
SdpMsidSemanticAttributeList::Serialize(std::ostream& os) const
{
for (auto i = mMsidSemantics.begin(); i != mMsidSemantics.end(); ++i) {
os << "a=" << mType << ":" << i->semantic;
for (auto j = i->msids.begin(); j != i->msids.end(); ++j) {
os << " " << *j;
}
os << CRLF;
}
}
void
SdpRemoteCandidatesAttribute::Serialize(std::ostream& os) const
{

View File

@ -630,6 +630,36 @@ public:
std::vector<Msid> mMsids;
};
///////////////////////////////////////////////////////////////////////////
// a=msid-semantic, draft-ietf-mmusic-msid
//-------------------------------------------------------------------------
// msid-semantic-attr = "msid-semantic:" msid-semantic msid-list
// msid-semantic = token ; see RFC 4566
// msid-list = *(" " msid-id) / " *"
class SdpMsidSemanticAttributeList : public SdpAttribute
{
public:
SdpMsidSemanticAttributeList() : SdpAttribute(kMsidSemanticAttribute) {}
struct MsidSemantic
{
// TODO: Once we have some more of these, we might want to make an enum
std::string semantic;
std::vector<std::string> msids;
};
void
PushEntry(const std::string& semantic, const std::vector<std::string>& msids)
{
MsidSemantic value = {semantic, msids};
mMsidSemantics.push_back(value);
}
virtual void Serialize(std::ostream& os) const MOZ_OVERRIDE;
std::vector<MsidSemantic> mMsidSemantics;
};
///////////////////////////////////////////////////////////////////////////
// a=remote-candiate, RFC5245
//-------------------------------------------------------------------------

View File

@ -70,7 +70,7 @@ public:
virtual const std::string& GetLabel() const = 0;
virtual unsigned int GetMaxptime() const = 0;
virtual const std::string& GetMid() const = 0;
virtual const std::string& GetMsidSemantic() const = 0;
virtual const SdpMsidSemanticAttributeList& GetMsidSemantic() const = 0;
virtual unsigned int GetPtime() const = 0;
// This is "special", because it's multiple things

View File

@ -108,8 +108,6 @@ SipccSdpAttributeList::LoadSimpleStrings(sdp_t* sdp, uint16_t level,
errorHolder);
LoadSimpleString(sdp, level, SDP_ATTR_IDENTITY,
SdpAttribute::kIdentityAttribute, errorHolder);
LoadSimpleString(sdp, level, SDP_ATTR_MSID_SEMANTIC,
SdpAttribute::kMsidSemanticAttribute, errorHolder);
}
void
@ -547,6 +545,38 @@ SipccSdpAttributeList::LoadGroups(sdp_t* sdp, uint16_t level,
return true;
}
bool
SipccSdpAttributeList::LoadMsidSemantics(sdp_t* sdp, uint16_t level,
SdpErrorHolder& errorHolder)
{
auto msidSemantics = MakeUnique<SdpMsidSemanticAttributeList>();
for (uint16_t i = 1; i < UINT16_MAX; ++i) {
sdp_attr_t* attr = sdp_find_attr(sdp, level, 0, SDP_ATTR_MSID_SEMANTIC, i);
if (!attr) {
break;
}
sdp_msid_semantic_t* msid_semantic = &(attr->attr.msid_semantic);
std::vector<std::string> msids;
for (size_t i = 0; i < SDP_MAX_MEDIA_STREAMS; ++i) {
if (!msid_semantic->msids[i]) {
break;
}
msids.push_back(msid_semantic->msids[i]);
}
msidSemantics->PushEntry(msid_semantic->semantic, msids);
}
if (!msidSemantics->mMsidSemantics.empty()) {
SetAttribute(msidSemantics.release());
}
return true;
}
void
SipccSdpAttributeList::LoadFmtp(sdp_t* sdp, uint16_t level)
{
@ -829,6 +859,10 @@ SipccSdpAttributeList::Load(sdp_t* sdp, uint16_t level,
if (!LoadGroups(sdp, level, errorHolder)) {
return false;
}
if (!LoadMsidSemantics(sdp, level, errorHolder)) {
return false;
}
} else {
sdp_media_e mtype = sdp_get_media_type(sdp, level);
if (mtype == SDP_MEDIA_APPLICATION) {
@ -1045,14 +1079,14 @@ SipccSdpAttributeList::GetMsid() const
return *static_cast<const SdpMsidAttributeList*>(attr);
}
const std::string&
const SdpMsidSemanticAttributeList&
SipccSdpAttributeList::GetMsidSemantic() const
{
if (!HasAttribute(SdpAttribute::kMsidSemanticAttribute)) {
return kEmptyString;
MOZ_CRASH();
}
const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidSemanticAttribute);
return static_cast<const SdpStringAttribute*>(attr)->mValue;
return *static_cast<const SdpMsidSemanticAttributeList*>(attr);
}
uint32_t

View File

@ -69,7 +69,8 @@ public:
virtual const std::string& GetLabel() const MOZ_OVERRIDE;
virtual unsigned int GetMaxptime() const MOZ_OVERRIDE;
virtual const std::string& GetMid() const MOZ_OVERRIDE;
virtual const std::string& GetMsidSemantic() const MOZ_OVERRIDE;
virtual const SdpMsidSemanticAttributeList& GetMsidSemantic()
const MOZ_OVERRIDE;
virtual unsigned int GetPtime() const MOZ_OVERRIDE;
virtual SdpDirectionAttribute::Direction GetDirection() const MOZ_OVERRIDE;
@ -105,6 +106,9 @@ private:
void LoadSetup(sdp_t* sdp, uint16_t level);
void LoadSsrc(sdp_t* sdp, uint16_t level);
bool LoadGroups(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
bool LoadMsidSemantics(sdp_t* sdp,
uint16_t level,
SdpErrorHolder& errorHolder);
void LoadFmtp(sdp_t* sdp, uint16_t level);
void LoadMsids(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadExtmap(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);

View File

@ -556,7 +556,7 @@ typedef enum sdp_srtp_crypto_suite_t_ {
/* Max number of stream ids that can be grouped together */
#define SDP_MAX_GROUP_STREAM_ID 10
#define SDP_MAX_MEDIA_STREAMS 10
#define SDP_MAGIC_NUM 0xabcdabcd
@ -838,9 +838,14 @@ typedef struct sdp_stream_data {
char x_confid[SDP_MAX_STRING_LEN+1];
sdp_group_attr_e group_attr; /* FID or LS */
uint16_t num_group_id;
char * group_ids[SDP_MAX_GROUP_STREAM_ID];
char * group_ids[SDP_MAX_MEDIA_STREAMS];
} sdp_stream_data_t;
typedef struct sdp_msid_semantic {
char semantic[SDP_MAX_STRING_LEN+1];
char * msids[SDP_MAX_MEDIA_STREAMS];
} sdp_msid_semantic_t;
/*
* a=source-filter:<filter-mode> <filter-spec>
* <filter-spec> = <nettype> <addrtype> <dest-addr> <src_addr><src_addr>...
@ -1009,6 +1014,7 @@ typedef struct sdp_attr {
sdp_srtp_crypto_context_t srtp_context;
sdp_mptime_t mptime;
sdp_stream_data_t stream_data;
sdp_msid_semantic_t msid_semantic;
char unknown[SDP_MAX_STRING_LEN+1];
sdp_source_filter_t source_filter;
sdp_fmtp_fb_t rtcp_fb;

View File

@ -4101,7 +4101,7 @@ sdp_result_e sdp_parse_attr_group (sdp_t *sdp_p, sdp_attr_t *attr_p,
*/
attr_p->attr.stream_data.num_group_id =0;
for (i=0; i<SDP_MAX_GROUP_STREAM_ID; i++) {
for (i=0; i<SDP_MAX_MEDIA_STREAMS; i++) {
ptr = sdp_getnextstrtok(ptr, tmp, sizeof(tmp), " \t", &result);
if (result != SDP_SUCCESS) {
@ -5315,6 +5315,82 @@ sdp_result_e sdp_build_attr_msid(sdp_t *sdp_p,
return SDP_SUCCESS;
}
sdp_result_e sdp_parse_attr_msid_semantic(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr)
{
sdp_result_e result;
int i;
ptr = sdp_getnextstrtok(ptr,
attr_p->attr.msid_semantic.semantic,
sizeof(attr_p->attr.msid_semantic.semantic),
" \t",
&result);
if (result != SDP_SUCCESS) {
sdp_parse_error(sdp_p, "%s Warning: Bad msid-semantic attribute; "
"missing semantic",
sdp_p->debug_str);
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
for (i = 0; i < SDP_MAX_MEDIA_STREAMS; ++i) {
/* msid-id can be up to 64 characters long, plus null terminator */
char temp[65];
ptr = sdp_getnextstrtok(ptr, temp, sizeof(temp), " \t", &result);
if (result != SDP_SUCCESS) {
break;
}
attr_p->attr.msid_semantic.msids[i] = cpr_strdup(temp);
}
if ((result != SDP_SUCCESS) && (result != SDP_EMPTY_TOKEN)) {
sdp_parse_error(sdp_p, "%s Warning: Bad msid-semantic attribute",
sdp_p->debug_str);
sdp_p->conf_p->num_invalid_param++;
return SDP_INVALID_PARAMETER;
}
if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
SDP_PRINT("%s Parsed a=msid-semantic, %s", sdp_p->debug_str,
attr_p->attr.msid_semantic.semantic);
for (i = 0; i < SDP_MAX_MEDIA_STREAMS; ++i) {
if (!attr_p->attr.msid_semantic.msids[i]) {
break;
}
SDP_PRINT("%s ... msid %s", sdp_p->debug_str,
attr_p->attr.msid_semantic.msids[i]);
}
}
return SDP_SUCCESS;
}
sdp_result_e sdp_build_attr_msid_semantic(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs)
{
int i;
flex_string_sprintf(fs, "a=msid-semantic:%s",
attr_p->attr.msid_semantic.semantic);
for (i = 0; i < SDP_MAX_MEDIA_STREAMS; ++i) {
if (!attr_p->attr.msid_semantic.msids[i]) {
break;
}
flex_string_sprintf(fs, " %s",
attr_p->attr.msid_semantic.msids[i]);
}
flex_string_sprintf(fs, "\r\n");
return SDP_SUCCESS;
}
sdp_result_e sdp_parse_attr_ssrc(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr)

View File

@ -605,6 +605,20 @@ void sdp_copy_attr_fields (sdp_attr_t *src_attr_p, sdp_attr_t *dst_attr_p)
}
break;
case SDP_ATTR_MSID_SEMANTIC:
sstrncpy(dst_attr_p->attr.msid_semantic.semantic,
src_attr_p->attr.msid_semantic.semantic,
SDP_MAX_STRING_LEN+1);
for (i=0; i < SDP_MAX_MEDIA_STREAMS; ++i) {
if (!src_attr_p->attr.msid_semantic.msids[i]) {
break;
}
dst_attr_p->attr.msid_semantic.msids[i] =
cpr_strdup(src_attr_p->attr.msid_semantic.msids[i]);
}
break;
case SDP_ATTR_SOURCE_FILTER:
dst_attr_p->attr.source_filter.mode =
src_attr_p->attr.source_filter.mode;
@ -1176,6 +1190,10 @@ void sdp_free_attr (sdp_attr_t *attr_p)
for (i = 0; i < attr_p->attr.stream_data.num_group_id; i++) {
SDP_FREE(attr_p->attr.stream_data.group_ids[i]);
}
} else if (attr_p->type == SDP_ATTR_MSID_SEMANTIC) {
for (i = 0; i < SDP_MAX_MEDIA_STREAMS; ++i) {
SDP_FREE(attr_p->attr.msid_semantic.msids[i]);
}
}
/* Now free the actual attribute memory. */
@ -1658,7 +1676,6 @@ static boolean sdp_attr_is_simple_string(sdp_attr_e attr_type) {
(attr_type != SDP_ATTR_X_CONFID) &&
(attr_type != SDP_ATTR_LABEL) &&
(attr_type != SDP_ATTR_IDENTITY) &&
(attr_type != SDP_ATTR_MSID_SEMANTIC) &&
(attr_type != SDP_ATTR_ICE_OPTIONS)) {
return FALSE;
}
@ -10305,7 +10322,7 @@ sdp_result_e sdp_set_group_num_id (void *sdp_ptr, uint16_t level,
}
sdp_p->conf_p->num_invalid_param++;
return (SDP_INVALID_PARAMETER);
} else if ((group_num_id == 0) || (group_num_id > SDP_MAX_GROUP_STREAM_ID)){
} else if ((group_num_id == 0) || (group_num_id > SDP_MAX_MEDIA_STREAMS)){
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag, "%s Number of group id value provided - %u is invalid",
sdp_p->debug_str, (unsigned)group_num_id);
@ -10388,7 +10405,7 @@ sdp_result_e sdp_set_group_id (void *sdp_ptr, uint16_t level,
return (SDP_INVALID_PARAMETER);
} else {
num_group_id = attr_p->attr.stream_data.num_group_id;
if (num_group_id == SDP_MAX_GROUP_STREAM_ID) {
if (num_group_id == SDP_MAX_MEDIA_STREAMS) {
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
CSFLogError(logTag, "%s Max number of Group Ids already defined "
"for this group line %u", sdp_p->debug_str, (unsigned)level);

View File

@ -185,7 +185,7 @@ const sdp_attrarray_t sdp_attr[SDP_MAX_ATTR_TYPES] =
{"msid", sizeof("msid"),
sdp_parse_attr_msid, sdp_build_attr_msid},
{"msid-semantic", sizeof("msid-semantic"),
sdp_parse_attr_simple_string, sdp_build_attr_simple_string},
sdp_parse_attr_msid_semantic, sdp_build_attr_msid_semantic},
{"bundle-only", sizeof("bundle-only"),
sdp_parse_attr_simple_flag, sdp_build_attr_simple_flag},
{"end-of-candidates", sizeof("end-of-candidates"),

View File

@ -80,6 +80,12 @@ extern sdp_result_e sdp_parse_attr_msid(sdp_t *sdp_p, sdp_attr_t *attr_p,
const char *ptr);
extern sdp_result_e sdp_build_attr_msid(sdp_t *sdp_p, sdp_attr_t *attr_p,
flex_string *fs);
extern sdp_result_e sdp_parse_attr_msid_semantic(sdp_t *sdp_p,
sdp_attr_t *attr_p,
const char *ptr);
extern sdp_result_e sdp_build_attr_msid_semantic(sdp_t *sdp_p,
sdp_attr_t *attr_p,
flex_string *fs);
extern sdp_result_e sdp_parse_attr_ssrc(sdp_t *sdp_p, sdp_attr_t *attr_p,
const char *ptr);
extern sdp_result_e sdp_build_attr_ssrc(sdp_t *sdp_p, sdp_attr_t *attr_p,

View File

@ -246,6 +246,20 @@ protected:
if (checkFlags & CHECK_TRACKS) {
// Check that the transports exist.
ASSERT_EQ(types.size(), mSessionOff.GetTransportCount());
for (size_t i = 0; i < types.size(); ++i) {
RefPtr<JsepTrack> ltrack;
ASSERT_EQ(NS_OK, mSessionOff.GetLocalTrack(i, &ltrack));
ASSERT_NE("", ltrack->GetStreamId());
ASSERT_NE("", ltrack->GetTrackId());
if (ltrack->GetMediaType() != SdpMediaSection::kApplication) {
std::string msidAttr("a=msid:");
msidAttr += ltrack->GetStreamId();
msidAttr += " ";
msidAttr += ltrack->GetTrackId();
ASSERT_NE(std::string::npos, offer.find(msidAttr))
<< "Did not find " << msidAttr << " in offer";
}
}
}
}
@ -265,6 +279,16 @@ protected:
RefPtr<JsepTrack> rtrack;
ASSERT_EQ(NS_OK, mSessionAns.GetRemoteTrack(i, &rtrack));
ASSERT_EQ(types[i], rtrack->GetMediaType());
ASSERT_NE("", rtrack->GetStreamId());
ASSERT_NE("", rtrack->GetTrackId());
if (rtrack->GetMediaType() != SdpMediaSection::kApplication) {
std::string msidAttr("a=msid:");
msidAttr += rtrack->GetStreamId();
msidAttr += " ";
msidAttr += rtrack->GetTrackId();
ASSERT_NE(std::string::npos, offer.find(msidAttr))
<< "Did not find " << msidAttr << " in offer";
}
}
}
}
@ -287,6 +311,21 @@ protected:
ASSERT_EQ(types[i], pair->mSending->GetMediaType());
ASSERT_TRUE(pair->mReceiving);
ASSERT_EQ(types[i], pair->mReceiving->GetMediaType());
ASSERT_NE("", pair->mSending->GetStreamId());
ASSERT_NE("", pair->mSending->GetTrackId());
// These might have been in the SDP, or might have been randomly
// chosen by JsepSessionImpl
ASSERT_NE("", pair->mReceiving->GetStreamId());
ASSERT_NE("", pair->mReceiving->GetTrackId());
if (pair->mReceiving->GetMediaType() != SdpMediaSection::kApplication) {
std::string msidAttr("a=msid:");
msidAttr += pair->mSending->GetStreamId();
msidAttr += " ";
msidAttr += pair->mSending->GetTrackId();
ASSERT_NE(std::string::npos, answer.find(msidAttr))
<< "Did not find " << msidAttr << " in offer";
}
}
}
DumpTrackPairs(mSessionOff);
@ -302,14 +341,29 @@ protected:
if (checkFlags & CHECK_TRACKS) {
// Verify that the right stuff is in the tracks.
ASSERT_EQ(types.size(), mSessionAns.GetNegotiatedTrackPairCount());
ASSERT_EQ(types.size(), mSessionOff.GetNegotiatedTrackPairCount());
for (size_t i = 0; i < types.size(); ++i) {
const JsepTrackPair* pair;
ASSERT_EQ(NS_OK, mSessionAns.GetNegotiatedTrackPair(i, &pair));
ASSERT_EQ(NS_OK, mSessionOff.GetNegotiatedTrackPair(i, &pair));
ASSERT_TRUE(pair->mSending);
ASSERT_EQ(types[i], pair->mSending->GetMediaType());
ASSERT_TRUE(pair->mReceiving);
ASSERT_EQ(types[i], pair->mReceiving->GetMediaType());
ASSERT_NE("", pair->mSending->GetStreamId());
ASSERT_NE("", pair->mSending->GetTrackId());
// These might have been in the SDP, or might have been randomly
// chosen by JsepSessionImpl
ASSERT_NE("", pair->mReceiving->GetStreamId());
ASSERT_NE("", pair->mReceiving->GetTrackId());
if (pair->mReceiving->GetMediaType() != SdpMediaSection::kApplication) {
std::string msidAttr("a=msid:");
msidAttr += pair->mReceiving->GetStreamId();
msidAttr += " ";
msidAttr += pair->mReceiving->GetTrackId();
ASSERT_NE(std::string::npos, answer.find(msidAttr))
<< "Did not find " << msidAttr << " in offer";
}
}
}
DumpTrackPairs(mSessionAns);

View File

@ -1126,7 +1126,8 @@ const std::string kBasicAudioVideoOffer =
"a=ice-pwd:e4cc12a910f106a0a744719425510e17" CRLF
"a=ice-lite" CRLF
"a=ice-options:trickle foo" CRLF
"a=msid-semantic:WMS plus" CRLF
"a=msid-semantic:WMS stream streama" CRLF
"a=msid-semantic:foo stream" CRLF
"a=fingerprint:sha-256 DF:2E:AC:8A:FD:0A:8E:99:BF:5D:E8:3C:E7:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:A0:72:9B:14:08:6D:0F:4C" CRLF
"a=identity:blahblahblah foo;bar" CRLF
"a=group:BUNDLE first second" CRLF
@ -1149,7 +1150,7 @@ const std::string kBasicAudioVideoOffer =
"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level" CRLF
"a=setup:actpass" CRLF
"a=rtcp-mux" CRLF
"a=msid:track stream" CRLF
"a=msid:stream track" CRLF
"a=candidate:0 1 UDP 2130379007 10.0.0.36 62453 typ host" CRLF
"a=candidate:2 1 UDP 1694236671 24.6.134.204 62453 typ srflx raddr 10.0.0.36 rport 62453" CRLF
"a=candidate:3 1 UDP 100401151 162.222.183.171 49761 typ relay raddr 162.222.183.171 rport 49761" CRLF
@ -1171,8 +1172,8 @@ const std::string kBasicAudioVideoOffer =
"a=rtcp-fb:120 ccm fir" CRLF
"a=setup:active" CRLF
"a=rtcp-mux" CRLF
"a=msid:tracka streama" CRLF
"a=msid:trackb streamb" CRLF
"a=msid:streama tracka" CRLF
"a=msid:streamb trackb" CRLF
"a=candidate:0 1 UDP 2130379007 10.0.0.36 59530 typ host" CRLF
"a=candidate:0 2 UDP 2130379006 10.0.0.36 64378 typ host" CRLF
"a=candidate:2 2 UDP 1694236670 24.6.134.204 64378 typ srflx raddr 10.0.0.36 rport 64378" CRLF
@ -1426,7 +1427,7 @@ const std::string kH264AudioVideoOffer =
"a=ice-ufrag:4a799b2e" CRLF
"a=ice-pwd:e4cc12a910f106a0a744719425510e17" CRLF
"a=ice-lite" CRLF
"a=msid-semantic:WMS plus" CRLF
"a=msid-semantic:WMS stream streama" CRLF
"a=fingerprint:sha-256 DF:2E:AC:8A:FD:0A:8E:99:BF:5D:E8:3C:E7:FA:FB:08:3B:3C:54:1D:D7:D4:05:77:A0:72:9B:14:08:6D:0F:4C" CRLF
"a=group:BUNDLE first second" CRLF
"a=group:BUNDLE third" CRLF
@ -1448,7 +1449,7 @@ const std::string kH264AudioVideoOffer =
"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level" CRLF
"a=setup:actpass" CRLF
"a=rtcp-mux" CRLF
"a=msid:track stream" CRLF
"a=msid:stream track" CRLF
"a=candidate:0 1 UDP 2130379007 10.0.0.36 62453 typ host" CRLF
"a=candidate:2 1 UDP 1694236671 24.6.134.204 62453 typ srflx raddr 10.0.0.36 rport 62453" CRLF
"a=candidate:3 1 UDP 100401151 162.222.183.171 49761 typ relay raddr 162.222.183.171 rport 49761" CRLF
@ -1469,8 +1470,8 @@ const std::string kH264AudioVideoOffer =
"a=recvonly" CRLF
"a=setup:active" CRLF
"a=rtcp-mux" CRLF
"a=msid:tracka streama" CRLF
"a=msid:trackb streamb" CRLF
"a=msid:streama tracka" CRLF
"a=msid:streamb trackb" CRLF
"a=candidate:0 1 UDP 2130379007 10.0.0.36 59530 typ host" CRLF
"a=candidate:0 2 UDP 2130379006 10.0.0.36 64378 typ host" CRLF
"a=candidate:2 2 UDP 1694236670 24.6.134.204 64378 typ srflx raddr 10.0.0.36 rport 64378" CRLF
@ -1672,22 +1673,29 @@ TEST_P(NewSdpTest, CheckMsid) {
ParseSdp(kBasicAudioVideoOffer);
ASSERT_TRUE(mSdp->GetAttributeList().HasAttribute(
SdpAttribute::kMsidSemanticAttribute));
// note that we lose the extra pieces here
// it's not worth it to save them until they mean something
ASSERT_EQ("WMS", mSdp->GetAttributeList().GetMsidSemantic());
auto semantics = mSdp->GetAttributeList().GetMsidSemantic().mMsidSemantics;
ASSERT_EQ(2U, semantics.size());
ASSERT_EQ("WMS", semantics[0].semantic);
ASSERT_EQ(2U, semantics[0].msids.size());
ASSERT_EQ("stream", semantics[0].msids[0]);
ASSERT_EQ("streama", semantics[0].msids[1]);
ASSERT_EQ("foo", semantics[1].semantic);
ASSERT_EQ(1U, semantics[1].msids.size());
ASSERT_EQ("stream", semantics[1].msids[0]);
const SdpMsidAttributeList& msids1 =
mSdp->GetMediaSection(0).GetAttributeList().GetMsid();
ASSERT_EQ(1U, msids1.mMsids.size());
ASSERT_EQ("track", msids1.mMsids[0].identifier);
ASSERT_EQ("stream", msids1.mMsids[0].appdata);
ASSERT_EQ("stream", msids1.mMsids[0].identifier);
ASSERT_EQ("track", msids1.mMsids[0].appdata);
const SdpMsidAttributeList& msids2 =
mSdp->GetMediaSection(1).GetAttributeList().GetMsid();
ASSERT_EQ(2U, msids2.mMsids.size());
ASSERT_EQ("tracka", msids2.mMsids[0].identifier);
ASSERT_EQ("streama", msids2.mMsids[0].appdata);
ASSERT_EQ("trackb", msids2.mMsids[1].identifier);
ASSERT_EQ("streamb", msids2.mMsids[1].appdata);
ASSERT_EQ("streama", msids2.mMsids[0].identifier);
ASSERT_EQ("tracka", msids2.mMsids[0].appdata);
ASSERT_EQ("streamb", msids2.mMsids[1].identifier);
ASSERT_EQ("trackb", msids2.mMsids[1].appdata);
const SdpMsidAttributeList& msids3 =
mSdp->GetMediaSection(2).GetAttributeList().GetMsid();
ASSERT_EQ(1U, msids3.mMsids.size());