MyHandler::setupTrack

    void setupTrack(size_t index) {
        //由会话描述对象mSessionDesc和参数index创建一个APacketSource类型对象
        sp<APacketSource> source =
            new APacketSource(mSessionDesc, index);

        if (source->initCheck() != OK) {
            ALOGW("Unsupported format. Ignoring track #%zu.", index);

            //对APacketSource类型对象source未能成功初始化的情况进行处理
            //创建一个回应消息reply,消息名为'setu',消息的处理者为this,也即MyHandler
            //将参数index设置到"index"字段
            //将错误码ERROR_UNSUPPORTED设置到"result"字段
            //发送该异步处理消息并返回
            sp<AMessage> reply = new AMessage('setu', this);
            reply->setSize("index", index);
            reply->setInt32("result", ERROR_UNSUPPORTED);
            reply->post();
            return;
        }

        //代码执行到这里说明该APacketSource类型对象source成功完成了初始化
        //从会话描述对象mSessionDesc里获取索引为index,key为"a=control"的value
        AString url;
        CHECK(mSessionDesc->findAttribute(index, "a=control", &url));

        //合并mBaseURL和url得到最终表述的媒体的位置
        AString trackURL;
        CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL));

        //向容器mTracks里添加一个TrackInfo对象
        //并完成一些初始化工作
        mTracks.push(TrackInfo());
        TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1);
        //设置媒体的位置info->mURL
        info->mURL = trackURL;
        //设置媒体源对象info->mPacketSource
        info->mPacketSource = source;
        //设置是否使用InterleavedTCP
        info->mUsingInterleavedTCP = false;
        info->mFirstSeqNumInSegment = 0;
        info->mNewSegment = true;
        info->mAllowedStaleAccessUnits = kMaxAllowedStaleAccessUnits;
        //初始化RTP和RTCP的套接字描述符
        info->mRTPSocket = -1;
        info->mRTCPSocket = -1;
        info->mRTPAnchor = 0;
        info->mNTPAnchorUs = -1;
        //初始化NTP
        info->mNormalPlayTimeRTP = 0;
        info->mNormalPlayTimeUs = 0ll;

        //由会话描述对象mSessionDesc的到索引为index的变量PT,formatDesc,formatParams的值
        unsigned long PT;
        AString formatDesc;
        AString formatParams;
        mSessionDesc->getFormatType(index, &PT, &formatDesc, &formatParams);

        //由formatDesc.c_str()得到变量timescale和numChannels的值
        //如何获取在后续的文章介绍
        int32_t timescale;
        int32_t numChannels;
        ASessionDescription::ParseFormatDesc(
                formatDesc.c_str(), &timescale, &numChannels);

        info->mTimeScale = timescale;
        info->mEOSReceived = false;

        ALOGV("track #%zu URL=%s", mTracks.size(), trackURL.c_str());

        //构建请求消息request 方法名为SETUP
        AString request = "SETUP ";
        request.append(trackURL);
        request.append(" RTSP/1.0\r\n");

        if (mTryTCPInterleaving) {
            //mTryTCPInterleaving成员变量的值在MyHandler的构造函数中被初始化为false
            size_t interleaveIndex = 2 * (mTracks.size() - 1);
            info->mUsingInterleavedTCP = true;
            info->mRTPSocket = interleaveIndex;
            info->mRTCPSocket = interleaveIndex + 1;

            request.append("Transport: RTP/AVP/TCP;interleaved=");
            request.append(interleaveIndex);
            request.append("-");
            request.append(interleaveIndex + 1);
        } else {
            //调用AVMediaServiceUtils::get()->makePortPair函数构建RTP套接字描述符和RTCP套接字描述符以及rtp端口号
            unsigned rtpPort;
            AVMediaServiceUtils::get()->makePortPair(
                    &info->mRTPSocket, &info->mRTCPSocket, &rtpPort,
                    mConn->isIPV6());

            if (mUIDValid) {
                HTTPBase::RegisterSocketUserTag(info->mRTPSocket, mUID,
                                                (uint32_t)*(uint32_t*) "RTP_");
                HTTPBase::RegisterSocketUserTag(info->mRTCPSocket, mUID,
                                                (uint32_t)*(uint32_t*) "RTP_");
                HTTPBase::RegisterSocketUserMark(info->mRTPSocket, mUID);
                HTTPBase::RegisterSocketUserMark(info->mRTCPSocket, mUID);
            }

            //添加Transport消息头
            //即将rtp端口号添加进去,以及加1作为rtcp端口号
            request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
            request.append(rtpPort);
            request.append("-");
            request.append(rtpPort + 1);
        }

        request.append("\r\n");

        if (index > 1) {
            //如果index大于1,添加Session消息头部
            request.append("Session: ");
            request.append(mSessionID);
            request.append("\r\n");
        }

        //添加消息头部和消息体的分隔符
        request.append("\r\n");

        //新建回应消息reply,消息名为'setu',消息处理者为this,即为MyHandler
        //将index添加到reply的"index"字段
        //将mTracks.size() - 1添加到reply的"track-index"字段
        sp<AMessage> reply = new AMessage('setu', this);
        reply->setSize("index", index);
        reply->setSize("track-index", mTracks.size() - 1);
        //调用mConn->sendRequest发用请求消息request.c_str()
        //回应消息reply被暂存在mConn(sp<ARTSPConnection>)对象的mPendingRequests容器里
        //直到服务端发送来对应的应答消息,该异步处理reply消息被发送出去
        mConn->sendRequest(request.c_str(), reply);
    }

  给出一个SETUP方法的会话例子:
  

    C->S: SETUP rtsp://example.com/foo/bar/baz.rm RTSP/1.0
          CSeq: 302
          Transport: RTP/AVP;unicast;client_port=4588-4589

    S->C: RTSP/1.0 200 OK
          CSeq: 302
          Date: 23 Jan 1997 15:35:06 GMT
          Session: 47112344
          Transport: RTP/AVP;unicast;
            client_port=4588-4589;server_port=6256-6257
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值