MyHandler::setupTrack

来源:互联网 发布:体育比赛直播软件 编辑:程序博客网 时间:2024/06/08 14:42
    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