ASessionDescription::parse

  安卓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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值