Bug 1212907 - a=rid support. r=mt

--HG--
extra : rebase_source : a9547d76a83de75304db263a5beb67295a362238
This commit is contained in:
Byron Campen [:bwc] 2015-10-08 16:55:39 -05:00
Родитель 90c27bffd6
Коммит 61d275e7db
10 изменённых файлов: 942 добавлений и 65 удалений

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

@ -147,6 +147,34 @@ void SdpIdentityAttribute::Serialize(std::ostream& os) const
}
#endif
// Class to help with omitting a leading delimiter for the first item in a list
class SkipFirstDelimiter
{
public:
explicit SkipFirstDelimiter(const std::string& delim) :
mDelim(delim),
mFirst(true)
{}
std::ostream& print(std::ostream& os)
{
if (!mFirst) {
os << mDelim;
}
mFirst = false;
return os;
}
private:
std::string mDelim;
bool mFirst;
};
static std::ostream& operator<<(std::ostream& os, SkipFirstDelimiter& delim)
{
return delim.print(os);
}
void
SdpImageattrAttributeList::XYRange::Serialize(std::ostream& os) const
{
@ -160,13 +188,9 @@ SdpImageattrAttributeList::XYRange::Serialize(std::ostream& os) const
os << discreteValues.front();
} else {
os << "[";
bool first = true;
SkipFirstDelimiter comma(",");
for (auto value : discreteValues) {
if (!first) {
os << ",";
}
first = false;
os << value;
os << comma << value;
}
os << "]";
}
@ -442,13 +466,9 @@ SdpImageattrAttributeList::SRange::Serialize(std::ostream& os) const
os << discreteValues.front();
} else {
os << "[";
bool first = true;
SkipFirstDelimiter comma(",");
for (auto value : discreteValues) {
if (!first) {
os << ",";
}
first = false;
os << value;
os << comma << value;
}
os << "]";
}
@ -461,19 +481,29 @@ SdpImageattrAttributeList::PRange::Serialize(std::ostream& os) const
os << "[" << min << "-" << max << "]";
}
static std::string ParseKey(std::istream& is, std::string* error)
static std::string ParseToken(std::istream& is,
const std::string& delims,
std::string* error)
{
is >> std::ws;
std::string key;
while (is && PeekChar(is, error) != '=') {
key.push_back(std::tolower(is.get()));
std::string token;
while (is) {
unsigned char c = PeekChar(is, error);
if (!c || (delims.find(c) != std::string::npos)) {
break;
}
token.push_back(std::tolower(is.get()));
}
return token;
}
static std::string ParseKey(std::istream& is, std::string* error)
{
std::string token = ParseToken(is, "=", error);
if (!SkipChar(is, '=', error)) {
return "";
}
return key;
return token;
}
static bool SkipBraces(std::istream& is, std::string* error)
@ -630,31 +660,11 @@ SdpImageattrAttributeList::Set::Serialize(std::ostream& os) const
os << "]";
}
static std::string
GetLowercaseToken(std::istream& is, std::string* error)
{
is >> std::ws;
std::string token;
while (true) {
switch (PeekChar(is, error)) {
case '\0':
case ' ':
case '\t':
return token;
default:
token.push_back(std::tolower(is.get()));
}
}
MOZ_ASSERT_UNREACHABLE("Unexpected break in loop");
return "";
}
bool
SdpImageattrAttributeList::Imageattr::ParseSets(std::istream& is,
std::string* error)
{
std::string type = GetLowercaseToken(is, error);
std::string type = ParseToken(is, " \t", error);
bool* isAll = nullptr;
std::vector<Set>* sets = nullptr;
@ -827,6 +837,201 @@ SdpRemoteCandidatesAttribute::Serialize(std::ostream& os) const
os << CRLF;
}
bool
SdpRidAttributeList::Constraints::Parse(std::istream& is, std::string* error)
{
if (!PeekChar(is, error)) {
// No constraints
return true;
}
do {
std::string key = ParseKey(is, error);
if (key.empty()) {
return false; // Illegal trailing cruft
}
// This allows pt= to appear anywhere, instead of only at the beginning, but
// this ends up being significantly less code.
if (key == "pt") {
if (!ParseFormats(is, error)) {
return false;
}
} else if (key == "max-width") {
if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &maxWidth, error)) {
return false;
}
} else if (key == "max-height") {
if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &maxHeight, error)) {
return false;
}
} else if (key == "max-fps") {
if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &maxFps, error)) {
return false;
}
} else if (key == "max-fs") {
if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &maxFs, error)) {
return false;
}
} else if (key == "max-br") {
if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &maxBr, error)) {
return false;
}
} else if (key == "max-pps") {
if (!GetUnsigned<uint32_t>(is, 0, UINT32_MAX, &maxPps, error)) {
return false;
}
} else if (key == "depend") {
if (!ParseDepend(is, error)) {
return false;
}
} else {
(void) ParseToken(is, ";", error);
}
} while (SkipChar(is, ';', error));
return true;
}
bool
SdpRidAttributeList::Constraints::ParseDepend(
std::istream& is,
std::string* error)
{
do {
std::string id = ParseToken(is, ",;", error);
if (id.empty()) {
return false;
}
dependIds.push_back(id);
} while(SkipChar(is, ',', error));
return true;
}
bool
SdpRidAttributeList::Constraints::ParseFormats(
std::istream& is,
std::string* error)
{
do {
uint16_t fmt;
if (!GetUnsigned<uint16_t>(is, 0, 127, &fmt, error)) {
return false;
}
formats.push_back(fmt);
} while (SkipChar(is, ',', error));
return true;
}
void
SdpRidAttributeList::Constraints::Serialize(std::ostream& os) const
{
if (!IsSet()) {
return;
}
os << " ";
SkipFirstDelimiter semic(";");
if (!formats.empty()) {
os << semic << "pt=";
SkipFirstDelimiter comma(",");
for (uint16_t fmt : formats) {
os << comma << fmt;
}
}
if (maxWidth) {
os << semic << "max-width=" << maxWidth;
}
if (maxHeight) {
os << semic << "max-height=" << maxHeight;
}
if (maxFps) {
os << semic << "max-fps=" << maxFps;
}
if (maxFs) {
os << semic << "max-fs=" << maxFs;
}
if (maxBr) {
os << semic << "max-br=" << maxBr;
}
if (maxPps) {
os << semic << "max-pps=" << maxPps;
}
if (!dependIds.empty()) {
os << semic << "depend=";
SkipFirstDelimiter comma(",");
for (const std::string& id : dependIds) {
os << comma << id;
}
}
}
bool
SdpRidAttributeList::Rid::Parse(std::istream& is, std::string* error)
{
id = ParseToken(is, " ", error);
if (id.empty()) {
return false;
}
std::string directionToken = ParseToken(is, " ", error);
if (directionToken == "send") {
direction = sdp::kSend;
} else if (directionToken == "recv") {
direction = sdp::kRecv;
} else {
*error = "Invalid direction, must be either send or recv";
return false;
}
return constraints.Parse(is, error);
}
void
SdpRidAttributeList::Rid::Serialize(std::ostream& os) const
{
os << id << " " << direction;
constraints.Serialize(os);
}
void
SdpRidAttributeList::Serialize(std::ostream& os) const
{
for (const Rid& rid : mRids) {
os << "a=" << mType << ":";
rid.Serialize(os);
os << CRLF;
}
}
bool
SdpRidAttributeList::PushEntry(const std::string& raw,
std::string* error,
size_t* errorPos)
{
std::istringstream is(raw);
Rid rid;
if (!rid.Parse(is, error)) {
is.clear();
*errorPos = is.tellg();
return false;
}
mRids.push_back(rid);
return true;
}
void
SdpRtcpAttribute::Serialize(std::ostream& os) const
{
@ -913,15 +1118,9 @@ SdpSetupAttribute::Serialize(std::ostream& os) const
void
SdpSimulcastAttribute::Version::Serialize(std::ostream& os) const
{
bool first = true;
SkipFirstDelimiter comma(",");
for (uint16_t format : choices) {
if (first) {
first = false;
} else {
os << ",";
}
os << format;
os << comma << format;
}
}
@ -965,18 +1164,12 @@ SdpSimulcastAttribute::Version::AddChoice(const std::string& pt)
void
SdpSimulcastAttribute::Versions::Serialize(std::ostream& os) const
{
bool first = true;
SkipFirstDelimiter semic(";");
for (const Version& version : *this) {
if (!version.IsSet()) {
continue;
}
if (first) {
first = false;
} else {
os << ";";
}
os << semic;
version.Serialize(os);
}
}
@ -1030,7 +1223,7 @@ SdpSimulcastAttribute::Parse(std::istream& is, std::string* error)
bool gotSendrecv = false;
while (true) {
std::string token = GetLowercaseToken(is, error);
std::string token = ParseToken(is, " \t", error);
if (token.empty()) {
break;
}
@ -1216,6 +1409,8 @@ SdpAttribute::IsAllowedAtMediaLevel(AttributeType type)
return true;
case kRemoteCandidatesAttribute:
return true;
case kRidAttribute:
return true;
case kRtcpAttribute:
return true;
case kRtcpFbAttribute:
@ -1298,6 +1493,8 @@ SdpAttribute::IsAllowedAtSessionLevel(AttributeType type)
return true;
case kRemoteCandidatesAttribute:
return false;
case kRidAttribute:
return false;
case kRtcpAttribute:
return false;
case kRtcpFbAttribute:
@ -1378,6 +1575,8 @@ SdpAttribute::GetAttributeTypeString(AttributeType type)
return "recvonly";
case kRemoteCandidatesAttribute:
return "remote-candidates";
case kRidAttribute:
return "rid";
case kRtcpAttribute:
return "rtcp";
case kRtcpFbAttribute:

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

@ -59,6 +59,7 @@ public:
kPtimeAttribute,
kRecvonlyAttribute,
kRemoteCandidatesAttribute,
kRidAttribute,
kRtcpAttribute,
kRtcpFbAttribute,
kRtcpMuxAttribute,
@ -771,6 +772,114 @@ public:
std::vector<Candidate> mCandidates;
};
/*
a=rid, draft-pthatcher-mmusic-rid-01
rid-syntax = "a=rid:" rid-identifier SP rid-dir
[ rid-pt-param-list / rid-param-list ]
rid-identifier = 1*(alpha-numeric / "-" / "_")
rid-dir = "send" / "recv"
rid-pt-param-list = SP rid-fmt-list *(";" rid-param)
rid-param-list = SP rid-param *(";" rid-param)
rid-fmt-list = "pt=" fmt *( "," fmt )
; fmt defined in {{RFC4566}}
rid-param = rid-width-param
/ rid-height-param
/ rid-fps-param
/ rid-fs-param
/ rid-br-param
/ rid-pps-param
/ rid-depend-param
/ rid-param-other
rid-width-param = "max-width" [ "=" int-param-val ]
rid-height-param = "max-height" [ "=" int-param-val ]
rid-fps-param = "max-fps" [ "=" int-param-val ]
rid-fs-param = "max-fs" [ "=" int-param-val ]
rid-br-param = "max-br" [ "=" int-param-val ]
rid-pps-param = "max-pps" [ "=" int-param-val ]
rid-depend-param = "depend=" rid-list
rid-param-other = 1*(alpha-numeric / "-") [ "=" param-val ]
rid-list = rid-identifier *( "," rid-identifier )
int-param-val = 1*DIGIT
param-val = *( %x20-58 / %x60-7E )
; Any printable character except semicolon
*/
class SdpRidAttributeList : public SdpAttribute
{
public:
explicit SdpRidAttributeList()
: SdpAttribute(kRidAttribute)
{}
struct Constraints
{
Constraints() :
maxWidth(0),
maxHeight(0),
maxFps(0),
maxFs(0),
maxBr(0),
maxPps(0)
{}
bool Parse(std::istream& is, std::string* error);
bool ParseDepend(std::istream& is, std::string* error);
bool ParseFormats(std::istream& is, std::string* error);
void Serialize(std::ostream& os) const;
bool IsSet() const
{
return !formats.empty() || maxWidth || maxHeight || maxFps || maxFs ||
maxBr || maxPps || !dependIds.empty();
}
std::vector<uint16_t> formats; // Empty implies all
uint32_t maxWidth;
uint32_t maxHeight;
uint32_t maxFps;
uint32_t maxFs;
uint32_t maxBr;
uint32_t maxPps;
std::vector<std::string> dependIds;
// We do not bother trying to store constraints we don't understand.
};
struct Rid
{
Rid() :
direction(sdp::kSend)
{}
bool Parse(std::istream& is, std::string* error);
void Serialize(std::ostream& os) const;
std::string id;
sdp::Direction direction;
Constraints constraints;
};
virtual void Serialize(std::ostream& os) const override;
bool PushEntry(const std::string& raw, std::string* error, size_t* errorPos);
std::vector<Rid> mRids;
};
///////////////////////////////////////////////////////////////////////////
// a=rtcp, RFC3605
//-------------------------------------------------------------------------

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

@ -58,6 +58,8 @@ public:
virtual const SdpImageattrAttributeList& GetImageattr() const = 0;
virtual const SdpSimulcastAttribute& GetSimulcast() const = 0;
virtual const SdpMsidAttributeList& GetMsid() const = 0;
virtual const SdpMsidSemanticAttributeList& GetMsidSemantic() const = 0;
virtual const SdpRidAttributeList& GetRid() const = 0;
virtual const SdpRtcpFbAttributeList& GetRtcpFb() const = 0;
virtual const SdpRtpmapAttributeList& GetRtpmap() const = 0;
virtual const SdpSctpmapAttributeList& GetSctpmap() const = 0;
@ -72,7 +74,6 @@ public:
virtual const std::string& GetLabel() const = 0;
virtual unsigned int GetMaxptime() const = 0;
virtual const std::string& GetMid() const = 0;
virtual const SdpMsidSemanticAttributeList& GetMsidSemantic() const = 0;
virtual unsigned int GetPtime() const = 0;
// This is "special", because it's multiple things

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

@ -52,6 +52,17 @@ enum Direction {
kRecv = 2
};
inline std::ostream& operator<<(std::ostream& os, sdp::Direction d)
{
switch (d) {
case sdp::kSend:
return os << "send";
case sdp::kRecv:
return os << "recv";
}
MOZ_CRASH("Unknown Direction");
}
} // namespace sdp
} // namespace mozilla

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

@ -513,8 +513,8 @@ SipccSdpAttributeList::LoadImageattr(sdp_t* sdp,
std::string error;
size_t errorPos;
if (!imageattrs->PushEntry(imageattrRaw, &error, &errorPos)) {
std::ostringstream fullError(error + " at column ");
fullError << errorPos;
std::ostringstream fullError;
fullError << error << " at column " << errorPos;
errorHolder.AddParseError(
sdp_attr_line_number(sdp, SDP_ATTR_IMAGEATTR, level, 0, i),
fullError.str());
@ -548,9 +548,8 @@ SipccSdpAttributeList::LoadSimulcast(sdp_t* sdp,
std::istringstream is(simulcastRaw);
std::string error;
if (!simulcast->Parse(is, &error)) {
is.clear();
std::ostringstream fullError(error + " at column ");
fullError << is.tellg();
std::ostringstream fullError;
fullError << error << " at column " << is.tellg();
errorHolder.AddParseError(
sdp_attr_line_number(sdp, SDP_ATTR_SIMULCAST, level, 0, 1),
fullError.str());
@ -783,6 +782,41 @@ SipccSdpAttributeList::LoadMsids(sdp_t* sdp, uint16_t level,
}
}
bool
SipccSdpAttributeList::LoadRid(sdp_t* sdp,
uint16_t level,
SdpErrorHolder& errorHolder)
{
UniquePtr<SdpRidAttributeList> rids(new SdpRidAttributeList);
for (uint16_t i = 1; i < UINT16_MAX; ++i) {
const char* ridRaw = sdp_attr_get_simple_string(sdp,
SDP_ATTR_RID,
level,
0,
i);
if (!ridRaw) {
break;
}
std::string error;
size_t errorPos;
if (!rids->PushEntry(ridRaw, &error, &errorPos)) {
std::ostringstream fullError;
fullError << error << " at column " << errorPos;
errorHolder.AddParseError(
sdp_attr_line_number(sdp, SDP_ATTR_RID, level, 0, i),
fullError.str());
return false;
}
}
if (!rids->mRids.empty()) {
SetAttribute(rids.release());
}
return true;
}
void
SipccSdpAttributeList::LoadExtmap(sdp_t* sdp, uint16_t level,
SdpErrorHolder& errorHolder)
@ -1000,6 +1034,9 @@ SipccSdpAttributeList::Load(sdp_t* sdp, uint16_t level,
if (!LoadSimulcast(sdp, level, errorHolder)) {
return false;
}
if (!LoadRid(sdp, level, errorHolder)) {
return false;
}
}
LoadIceAttributes(sdp, level);
@ -1224,6 +1261,16 @@ SipccSdpAttributeList::GetMsidSemantic() const
return *static_cast<const SdpMsidSemanticAttributeList*>(attr);
}
const SdpRidAttributeList&
SipccSdpAttributeList::GetRid() const
{
if (!HasAttribute(SdpAttribute::kRidAttribute)) {
MOZ_CRASH();
}
const SdpAttribute* attr = GetAttribute(SdpAttribute::kRidAttribute);
return *static_cast<const SdpRidAttributeList*>(attr);
}
uint32_t
SipccSdpAttributeList::GetPtime() const
{

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

@ -58,6 +58,9 @@ public:
virtual const SdpImageattrAttributeList& GetImageattr() const override;
const SdpSimulcastAttribute& GetSimulcast() const override;
virtual const SdpMsidAttributeList& GetMsid() const override;
virtual const SdpMsidSemanticAttributeList& GetMsidSemantic()
const override;
const SdpRidAttributeList& GetRid() const override;
virtual const SdpRtcpFbAttributeList& GetRtcpFb() const override;
virtual const SdpRtpmapAttributeList& GetRtpmap() const override;
virtual const SdpSctpmapAttributeList& GetSctpmap() const override;
@ -70,8 +73,6 @@ public:
virtual const std::string& GetLabel() const override;
virtual unsigned int GetMaxptime() const override;
virtual const std::string& GetMid() const override;
virtual const SdpMsidSemanticAttributeList& GetMsidSemantic()
const override;
virtual unsigned int GetPtime() const override;
virtual SdpDirectionAttribute::Direction GetDirection() const override;
@ -114,6 +115,7 @@ private:
SdpErrorHolder& errorHolder);
void LoadFmtp(sdp_t* sdp, uint16_t level);
void LoadMsids(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
bool LoadRid(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadExtmap(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadRtcpFb(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);
void LoadRtcp(sdp_t* sdp, uint16_t level, SdpErrorHolder& errorHolder);

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

@ -186,6 +186,7 @@ typedef enum {
SDP_ATTR_SSRC,
SDP_ATTR_IMAGEATTR,
SDP_ATTR_SIMULCAST,
SDP_ATTR_RID,
SDP_MAX_ATTR_TYPES,
SDP_ATTR_INVALID
} sdp_attr_e;

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

@ -684,7 +684,8 @@ static boolean sdp_attr_is_simple_string(sdp_attr_e attr_type) {
(attr_type != SDP_ATTR_IDENTITY) &&
(attr_type != SDP_ATTR_ICE_OPTIONS) &&
(attr_type != SDP_ATTR_IMAGEATTR) &&
(attr_type != SDP_ATTR_SIMULCAST)) {
(attr_type != SDP_ATTR_SIMULCAST) &&
(attr_type != SDP_ATTR_RID)) {
return FALSE;
}
return TRUE;

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

@ -198,6 +198,8 @@ const sdp_attrarray_t sdp_attr[SDP_MAX_ATTR_TYPES] =
sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
{"simulcast", sizeof("simulcast"),
sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
{"rid", sizeof("rid"),
sdp_parse_attr_complete_line, sdp_build_attr_simple_string},
};
/* Note: These *must* be in the same order as the enum types. */

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

@ -1196,6 +1196,8 @@ const std::string kBasicAudioVideoOffer =
"a=imageattr:120 send * recv *" CRLF
"a=imageattr:121 send [x=640,y=480] recv [x=640,y=480]" CRLF
"a=simulcast:sendrecv 120;121" CRLF
"a=rid:foo send" CRLF
"a=rid:bar recv pt=96;max-width=800;max-height=600" CRLF
"m=audio 9 RTP/SAVPF 0" CRLF
"a=mid:third" CRLF
"a=rtpmap:0 PCMU/8000" CRLF
@ -1758,6 +1760,36 @@ TEST_P(NewSdpTest, CheckMsid) {
ASSERT_EQ("", msids3.mMsids[0].appdata);
}
TEST_P(NewSdpTest, CheckRid)
{
ParseSdp(kBasicAudioVideoOffer);
ASSERT_TRUE(!!mSdp);
ASSERT_EQ(3U, mSdp->GetMediaSectionCount()) << "Wrong number of media sections";
ASSERT_FALSE(mSdp->GetAttributeList().HasAttribute(
SdpAttribute::kRidAttribute));
ASSERT_FALSE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
SdpAttribute::kRidAttribute));
ASSERT_TRUE(mSdp->GetMediaSection(1).GetAttributeList().HasAttribute(
SdpAttribute::kRidAttribute));
ASSERT_FALSE(mSdp->GetMediaSection(2).GetAttributeList().HasAttribute(
SdpAttribute::kRidAttribute));
const SdpRidAttributeList& rids =
mSdp->GetMediaSection(1).GetAttributeList().GetRid();
ASSERT_EQ(2U, rids.mRids.size());
ASSERT_EQ("foo", rids.mRids[0].id);
ASSERT_EQ(sdp::kSend, rids.mRids[0].direction);
ASSERT_EQ(0U, rids.mRids[0].constraints.formats.size());
ASSERT_EQ("bar", rids.mRids[1].id);
ASSERT_EQ(sdp::kRecv, rids.mRids[1].direction);
ASSERT_EQ(1U, rids.mRids[1].constraints.formats.size());
ASSERT_EQ(96U, rids.mRids[1].constraints.formats[0]);
ASSERT_EQ(800U, rids.mRids[1].constraints.maxWidth);
ASSERT_EQ(600U, rids.mRids[1].constraints.maxHeight);
}
TEST_P(NewSdpTest, CheckMediaLevelIceUfrag) {
ParseSdp(kBasicAudioVideoOffer);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
@ -3641,6 +3673,478 @@ TEST(NewSdpTestNoFixture, CheckSimulcastInvalidParse)
ParseInvalid<SdpSimulcastAttribute>(" sendrecv 8 sendrecv ", 20);
}
static SdpRidAttributeList::Constraints
ParseRidConstraints(const std::string& input)
{
std::istringstream is(input);
std::string error;
SdpRidAttributeList::Constraints constraints;
EXPECT_TRUE(constraints.Parse(is, &error)) << error
<< " for input \'" << input << "\'" ;
EXPECT_TRUE(is.eof());
return constraints;
}
TEST(NewSdpTestNoFixture, CheckRidConstraintsValidParse)
{
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints(""));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("pt=96"));
ASSERT_EQ(1U, constraints.formats.size());
ASSERT_EQ(96U, constraints.formats[0]);
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
// This is not technically permitted by the BNF, but the parse code is simpler
// if we allow it. If we decide to stop allowing this, this will need to be
// converted to an invalid parse test-case.
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-br=30000;pt=96"));
ASSERT_EQ(1U, constraints.formats.size());
ASSERT_EQ(96U, constraints.formats[0]);
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(30000U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("pt=96,97,98"));
ASSERT_EQ(3U, constraints.formats.size());
ASSERT_EQ(96U, constraints.formats[0]);
ASSERT_EQ(97U, constraints.formats[1]);
ASSERT_EQ(98U, constraints.formats[2]);
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-width=800"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(800U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-height=640"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(640U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-fps=30"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(30U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-fs=3600"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(3600U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-br=30000"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(30000U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-pps=9216000"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(9216000U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("depend=foo"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(1U, constraints.dependIds.size());
ASSERT_EQ("foo", constraints.dependIds[0]);
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-foo=20"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("depend=foo,bar"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(0U, constraints.maxWidth);
ASSERT_EQ(0U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(2U, constraints.dependIds.size());
ASSERT_EQ("foo", constraints.dependIds[0]);
ASSERT_EQ("bar", constraints.dependIds[1]);
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-width=800;max-height=600"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(800U, constraints.maxWidth);
ASSERT_EQ(600U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("pt=96,97;max-width=800;max-height=600"));
ASSERT_EQ(2U, constraints.formats.size());
ASSERT_EQ(96U, constraints.formats[0]);
ASSERT_EQ(97U, constraints.formats[1]);
ASSERT_EQ(800U, constraints.maxWidth);
ASSERT_EQ(600U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("depend=foo,bar;max-width=800;max-height=600"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(800U, constraints.maxWidth);
ASSERT_EQ(600U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(2U, constraints.dependIds.size());
ASSERT_EQ("foo", constraints.dependIds[0]);
ASSERT_EQ("bar", constraints.dependIds[1]);
}
{
SdpRidAttributeList::Constraints constraints(
ParseRidConstraints("max-foo=20;max-width=800;max-height=600"));
ASSERT_EQ(0U, constraints.formats.size());
ASSERT_EQ(800U, constraints.maxWidth);
ASSERT_EQ(600U, constraints.maxHeight);
ASSERT_EQ(0U, constraints.maxFps);
ASSERT_EQ(0U, constraints.maxFs);
ASSERT_EQ(0U, constraints.maxBr);
ASSERT_EQ(0U, constraints.maxPps);
ASSERT_EQ(0U, constraints.dependIds.size());
}
}
TEST(NewSdpTestNoFixture, CheckRidConstraintsInvalidParse)
{
ParseInvalid<SdpRidAttributeList::Constraints>(" ", 1);
ParseInvalid<SdpRidAttributeList::Constraints>("pt", 2);
ParseInvalid<SdpRidAttributeList::Constraints>("pt=", 3);
ParseInvalid<SdpRidAttributeList::Constraints>("pt=x", 3);
ParseInvalid<SdpRidAttributeList::Constraints>("pt=-1", 3);
ParseInvalid<SdpRidAttributeList::Constraints>("pt=96,", 6);
ParseInvalid<SdpRidAttributeList::Constraints>("pt=196", 6);
ParseInvalid<SdpRidAttributeList::Constraints>("max-width", 9);
ParseInvalid<SdpRidAttributeList::Constraints>("max-width=", 10);
ParseInvalid<SdpRidAttributeList::Constraints>("max-width=x", 10);
ParseInvalid<SdpRidAttributeList::Constraints>("max-width=-1", 10);
ParseInvalid<SdpRidAttributeList::Constraints>("max-width=800;", 14);
ParseInvalid<SdpRidAttributeList::Constraints>("max-width=800; ", 15);
ParseInvalid<SdpRidAttributeList::Constraints>("depend=", 7);
ParseInvalid<SdpRidAttributeList::Constraints>("depend=,", 7);
ParseInvalid<SdpRidAttributeList::Constraints>("depend=1,", 9);
}
TEST(NewSdpTestNoFixture, CheckRidConstraintsSerialize)
{
{
SdpRidAttributeList::Constraints constraints;
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ("", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.formats.push_back(96);
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" pt=96", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.formats.push_back(96);
constraints.formats.push_back(97);
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" pt=96,97", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.maxWidth = 800;
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" max-width=800", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.maxHeight = 600;
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" max-height=600", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.maxFps = 30;
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" max-fps=30", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.maxFs = 3600;
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" max-fs=3600", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.maxBr = 30000;
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" max-br=30000", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.maxPps = 9216000;
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" max-pps=9216000", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.dependIds.push_back("foo");
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" depend=foo", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.dependIds.push_back("foo");
constraints.dependIds.push_back("bar");
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" depend=foo,bar", os.str());
}
{
SdpRidAttributeList::Constraints constraints;
constraints.formats.push_back(96);
constraints.maxBr = 30000;
std::ostringstream os;
constraints.Serialize(os);
ASSERT_EQ(" pt=96;max-br=30000", os.str());
}
}
static SdpRidAttributeList::Rid
ParseRid(const std::string& input)
{
std::istringstream is(input);
std::string error;
SdpRidAttributeList::Rid rid;
EXPECT_TRUE(rid.Parse(is, &error)) << error;
EXPECT_TRUE(is.eof());
return rid;
}
TEST(NewSdpTestNoFixture, CheckRidValidParse)
{
{
SdpRidAttributeList::Rid rid(ParseRid("1 send"));
ASSERT_EQ("1", rid.id);
ASSERT_EQ(sdp::kSend, rid.direction);
ASSERT_EQ(0U, rid.constraints.formats.size());
ASSERT_EQ(0U, rid.constraints.maxWidth);
ASSERT_EQ(0U, rid.constraints.maxHeight);
ASSERT_EQ(0U, rid.constraints.maxFps);
ASSERT_EQ(0U, rid.constraints.maxFs);
ASSERT_EQ(0U, rid.constraints.maxBr);
ASSERT_EQ(0U, rid.constraints.maxPps);
ASSERT_EQ(0U, rid.constraints.dependIds.size());
}
{
SdpRidAttributeList::Rid rid(ParseRid("1 send pt=96;max-width=800"));
ASSERT_EQ("1", rid.id);
ASSERT_EQ(sdp::kSend, rid.direction);
ASSERT_EQ(1U, rid.constraints.formats.size());
ASSERT_EQ(96U, rid.constraints.formats[0]);
ASSERT_EQ(800U, rid.constraints.maxWidth);
ASSERT_EQ(0U, rid.constraints.maxHeight);
ASSERT_EQ(0U, rid.constraints.maxFps);
ASSERT_EQ(0U, rid.constraints.maxFs);
ASSERT_EQ(0U, rid.constraints.maxBr);
ASSERT_EQ(0U, rid.constraints.maxPps);
ASSERT_EQ(0U, rid.constraints.dependIds.size());
}
{
SdpRidAttributeList::Rid rid(ParseRid("1 send pt=96,97,98;max-width=800"));
ASSERT_EQ("1", rid.id);
ASSERT_EQ(sdp::kSend, rid.direction);
ASSERT_EQ(3U, rid.constraints.formats.size());
ASSERT_EQ(96U, rid.constraints.formats[0]);
ASSERT_EQ(97U, rid.constraints.formats[1]);
ASSERT_EQ(98U, rid.constraints.formats[2]);
ASSERT_EQ(800U, rid.constraints.maxWidth);
ASSERT_EQ(0U, rid.constraints.maxHeight);
ASSERT_EQ(0U, rid.constraints.maxFps);
ASSERT_EQ(0U, rid.constraints.maxFs);
ASSERT_EQ(0U, rid.constraints.maxBr);
ASSERT_EQ(0U, rid.constraints.maxPps);
ASSERT_EQ(0U, rid.constraints.dependIds.size());
}
{
SdpRidAttributeList::Rid rid(
ParseRid("0123456789az-_ recv max-width=800"));
ASSERT_EQ("0123456789az-_", rid.id);
ASSERT_EQ(sdp::kRecv, rid.direction);
ASSERT_EQ(0U, rid.constraints.formats.size());
ASSERT_EQ(800U, rid.constraints.maxWidth);
ASSERT_EQ(0U, rid.constraints.maxHeight);
ASSERT_EQ(0U, rid.constraints.maxFps);
ASSERT_EQ(0U, rid.constraints.maxFs);
ASSERT_EQ(0U, rid.constraints.maxBr);
ASSERT_EQ(0U, rid.constraints.maxPps);
ASSERT_EQ(0U, rid.constraints.dependIds.size());
}
}
TEST(NewSdpTestNoFixture, CheckRidInvalidParse)
{
ParseInvalid<SdpRidAttributeList::Rid>("", 0);
ParseInvalid<SdpRidAttributeList::Rid>(" ", 1);
ParseInvalid<SdpRidAttributeList::Rid>("foo", 3);
ParseInvalid<SdpRidAttributeList::Rid>("foo ", 4);
ParseInvalid<SdpRidAttributeList::Rid>("foo ", 5);
ParseInvalid<SdpRidAttributeList::Rid>("foo bar", 7);
ParseInvalid<SdpRidAttributeList::Rid>("foo recv ", 9);
ParseInvalid<SdpRidAttributeList::Rid>("foo recv pt=", 12);
}
TEST(NewSdpTestNoFixture, CheckRidSerialize)
{
{
SdpRidAttributeList::Rid rid;
rid.id = "foo";
rid.direction = sdp::kSend;
std::ostringstream os;
rid.Serialize(os);
ASSERT_EQ("foo send", os.str());
}
}
} // End namespace test.
int main(int argc, char **argv) {