安卓N版本ASessionDescription::parse函數原文:
bool ASessionDescription::parse(const void *data, size_t size) {
//先把mTracks和mFormats裏的內容清空
mTracks.clear();
mFormats.clear();
//向mTracks裏添加一個元素Attribs()
//Attribs是類型爲KeyedVector<AString,AString>的容器
//向mFormats容器裏添加一個元素AString("[root]")
//mFormats是類型爲Vector<AString>的容器
mTracks.push(Attribs());
mFormats.push(AString("[root]"));
//將指定緩衝區裏的內容拷貝到desc對象裏
AString desc((const char *)data, size);
//循環解析拷貝到desc對象裏的內容
//內容是按行劃分的
size_t i = 0;
for (;;) {
//從內容的位置i開始查找"\n"的位置
//返回位置i後最先出現的"\n"的位置eolPos
ssize_t eolPos = desc.find("\n", i);
if (eolPos < 0) {
//如果eolPos的值小於0,說明位置i後沒有"\n"了
//即到達了結尾,跳出循環
break;
}
AString line;
if ((size_t)eolPos > i && desc.c_str()[eolPos - 1] == '\r') {
// We accept both '\n' and '\r\n' line endings, if it's
// the latter, strip the '\r' as well.
//如果(size_t)eolPos > i,則說明
//desc.c_str()[i,eolPos - 1]是新的一行內容不包括desc.c_str()[eolPos]
//因爲desc.c_str()[eolPos] == '\n'
//如果desc.c_str()[eolPos - 1] == '\r'則將該字符去掉
//只將desc.c_str()[i,eolPos - 1 - 1]裏的內容拷貝進line裏
line.setTo(desc, i, eolPos - i - 1);
} else {
line.setTo(desc, i, eolPos - i);
}
if (line.empty()) {
//如果line內容爲空
//則迭代進行下一次循環
//將i的位置設置到下一行的首位置
i = eolPos + 1;
continue;
}
if (line.size() < 2 || line.c_str()[1] != '=') {
//如果line.size() < 2 或者 line.c_str()[1] != '='
//則說明這是一無效的行
//返回false結束循環
//有效一行的格式是:如"a=*****"
return false;
}
ALOGI("%s", line.c_str());
switch (line.c_str()[0]) {
case 'v':
{
//如果該行內容首字符爲'v'
//則判斷該行內容是否爲"v=0"
//如果不是則說明該行是一個無效的行返回false
if (strcmp(line.c_str(), "v=0")) {
return false;
}
break;
}
case 'a':
case 'b':
{
//解析該行內容首字符爲'a'和'b'的情況
//解析出一對兒key和value
AString key, value;
//查找key和value的分割符":"的位置colonPos
//一般情況下line.str()[0,colonPos-1]爲key
//line.str()[colonPos]爲":"
//line.str()[colonPos+1,line.size()-1]
ssize_t colonPos = line.find(":", 2);
if (colonPos < 0) {
//如果colonPos < 0
//說明該行沒有key和value的分割符":"
//即該行就是key,將line賦值給key
key = line;
} else {
//如果colonPos > 0
//則說明存在key和value的分割符":"
//line.str()[colonPos]爲":"
//將包含key的內容line.str()[0,colonPos-1]賦值到key裏
//通過函數key.setTo(line, 0, colonPos)完成
key.setTo(line, 0, colonPos);
if (key == "a=fmtp" || key == "a=rtpmap"
|| key == "a=framesize") {
//分析key爲 "a=fmtp" "a=rtpmap" "a=framesize"的情況
//從該行內容裏從key和value的分割符":"位置colonPos後查找" "的位置
//對應該種情況,從分隔符":"的位置colonPos開始查找" "的位置spacePos
ssize_t spacePos = line.find(" ", colonPos + 1);
if (spacePos < 0) {
//如果spacePos < 0說明分隔符":"後沒有" "的位置
//該行是無效的行,返回false
return false;
}
//重新設置key,
//此時key爲line.strz()[0,spacePos-1]
key.setTo(line, 0, spacePos);
//將" "的位置賦值給colonPos
colonPos = spacePos;
}
//line.strz()[colonPos + 1,line.size()-1]爲value
value.setTo(line, colonPos + 1, line.size() - colonPos - 1);
}
key.trim();
value.trim();
ALOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
//將解析出來的一對兒key和value添加到mTracks後一個元素所表示的容器裏
mTracks.editItemAt(mTracks.size() - 1).add(key, value);
break;
}
case 'm':
{
ALOGV("new section '%s'",
AString(line, 2, line.size() - 2).c_str());
//處理該行首字符爲'm'的情況
//向mTracks容器添加一個類型爲Attribs的元素
//將line.str()[2,line.size() - 1]裏的內容添加到mFormats容器裏
mTracks.push(Attribs());
mFormats.push(AString(line, 2, line.size() - 2));
break;
}
default:
{
//處理該行首字符爲其他字符的情況
AString key, value;
//從該行查找"="字符的位置
ssize_t equalPos = line.find("=");
//line.str()[0,equalPos]爲key
//line.str()[equalPos+1,line.size() -1]爲value
key = AString(line, 0, equalPos + 1);
value = AString(line, equalPos + 1, line.size() - equalPos - 1);
key.trim();
value.trim();
ALOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
mTracks.editItemAt(mTracks.size() - 1).add(key, value);
break;
}
}
//迭代解析下一行
i = eolPos + 1;
}
return true;
}
小結:
ASessionDescription::parse函數的功能就是根據內容格式解析出對應的key和value並用相應的數據結構存儲起來。
給出一個會話例子:
Example:
C->S: DESCRIBE rtsp://server.example.com/fizzle/foo RTSP/1.0
CSeq: 312
Accept: application/sdp, application/rtsl, application/mheg
S->C: RTSP/1.0 200 OK
CSeq: 312
Date: 23 Jan 1997 15:35:06 GMT
Content-Type: application/sdp
Content-Length: 376
v=0
o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4
s=SDP Seminar
i=A Seminar on the session description protocol
u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps
e=mjh@isi.edu (Mark Handley)
c=IN IP4 224.2.17.12/127
t=2873397496 2873404696
a=recvonly
m=audio 3456 RTP/AVP 0
m=video 2232 RTP/AVP 31
m=whiteboard 32416 UDP WB
a=orient:portrait