case 'setu':
{
//在消息msg的字段"index"得到index的值
size_t index;
CHECK(msg->findSize("index", &index));
TrackInfo *track = NULL;
size_t trackIndex;
//在消息msg的"track-index"字段得到trackIndex的值
if (msg->findSize("track-index", &trackIndex)) {
//由trackIndex得到对应的TrackInfo
track = &mTracks.editItemAt(trackIndex);
}
//由消息msg的"result"字段得到result的值
int32_t result;
CHECK(msg->findInt32("result", &result));
ALOGI("SETUP(%zu) completed with result %d (%s)",
index, result, strerror(-result));
if (result == OK) {
//如果result的值为OK,则说明成功收到了服务端的应答消息
CHECK(track != NULL);
//由消息msg的"response"字段得到应答消息对象response
sp<RefBase> obj;
CHECK(msg->findObject("response", &obj));
sp<ARTSPResponse> response =
static_cast<ARTSPResponse *>(obj.get());
if (response->mStatusCode != 200) {
//如果应答消息的状态码不为200
//则将错误码UNKNOWN_ERROR赋值给result
result = UNKNOWN_ERROR;
} else {
//代码执行到这里说明应答消息的状态码为200
//从应答消息中获取头部为session的值
//并赋值给mSessionID成员变量
ssize_t i = response->mHeaders.indexOfKey("session");
CHECK_GE(i, 0);
mSessionID = response->mHeaders.valueAt(i);
mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
//从mSessionID变量的值中获取timeoutStr的值
AString timeoutStr;
if (GetAttribute(
mSessionID.c_str(), "timeout", &timeoutStr)) {
//将字符串表示的timeoutStr的值转换成长整型数
char *end;
unsigned long timeoutSecs =
strtoul(timeoutStr.c_str(), &end, 10);
if (end == timeoutStr.c_str() || *end != '\0') {
ALOGW("server specified malformed timeout '%s'",
timeoutStr.c_str());
//如果转换遇到了错误
//使用默认的KeepAliveTimeoutUs
mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
} else if (timeoutSecs < 15) {
//如果转换得到的timeoutSecs小于15,使用默认的KeepAliveTimeoutUs
ALOGW("server specified too short a timeout "
"(%lu secs), using default.",
timeoutSecs);
mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
} else {
//如果转换得到的timeoutSecs大于或等于15
//使用指定的KeepAliveTimeoutUs
mKeepAliveTimeoutUs = timeoutSecs * 1000000ll;
ALOGI("server specified timeout of %lu secs.",
timeoutSecs);
}
}
AVMediaServiceUtils::get()->setServerTimeoutUs(mKeepAliveTimeoutUs);
//将"timeout=***"对应的字段从mSessionID中删除
i = mSessionID.find(";");
if (i >= 0) {
// Remove options, i.e. ";timeout=90"
mSessionID.erase(i, mSessionID.size() - i);
}
//新建一个异步通知消息notify
//消息名为'accu'
//消息处理者为this,也即MyHandler
//将trackIndex值设置到"track-index"字段
sp<AMessage> notify = new AMessage('accu', this);
notify->setSize("track-index", trackIndex);
//从应答消息里查找transport头部的值
i = response->mHeaders.indexOfKey("transport");
CHECK_GE(i, 0);
if (track->mRTPSocket != -1 && track->mRTCPSocket != -1) {
if (!track->mUsingInterleavedTCP) {
//得到应答消息transport头部的值
AString transport = response->mHeaders.valueAt(i);
// We are going to continue even if we were
// unable to poke a hole into the firewall...
//调用AVMediaServiceUtils::get()->pokeAHole进行防火墙处理
AVMediaServiceUtils::get()->pokeAHole(
this,
track->mRTPSocket,
track->mRTCPSocket,
transport,
mSessionHost);
}
//调用mRTPConn->addStream添加一个RTP流
//该函数在后续文章详细介绍
mRTPConn->addStream(
track->mRTPSocket, track->mRTCPSocket,
mSessionDesc, index,
notify, track->mUsingInterleavedTCP,
mConn->isIPV6());
//成功创建了一个track
//将mSetupTracksSuccessful的值赋值为true
mSetupTracksSuccessful = true;
} else {
//代码执行到这里说明track->mRTPSocket != -1 && track->mRTCPSocket != -1的值不为真
//将错误码BAD_VALUE赋值给result
result = BAD_VALUE;
}
}
}
if (result != OK) {
//如果上述过程中result的值不是OK
//则进行相应的错误处理
//关闭track->mRTPSocket描述的套接口
//关闭track->mRTCPSocket描述的套接口
if (track) {
if (!track->mUsingInterleavedTCP) {
// Clear the tag
if (mUIDValid) {
HTTPBase::UnRegisterSocketUserTag(track->mRTPSocket);
HTTPBase::UnRegisterSocketUserMark(track->mRTPSocket);
HTTPBase::UnRegisterSocketUserTag(track->mRTCPSocket);
HTTPBase::UnRegisterSocketUserMark(track->mRTCPSocket);
}
close(track->mRTPSocket);
close(track->mRTCPSocket);
}
//将该track从mTracks容器里删除
mTracks.removeItemsAt(trackIndex);
}
}
//将index所以自增1
++index;
if (result == OK && index < mSessionDesc->countTracks()) {
//如果还有其他的tarck
//继续调用setupTrack函数创建对应的tarck
setupTrack(index);
} else if (mSetupTracksSuccessful) {
//代码执行到这里
//说明所有的tarck都已经创建完毕
++mKeepAliveGeneration;
postKeepAlive();
//构建请求消息
//方法名为PLAY
AString request = "PLAY ";
request.append(mControlURL);
request.append(" RTSP/1.0\r\n");
//添加Session头部
request.append("Session: ");
request.append(mSessionID);
request.append("\r\n");
AVMediaServiceUtils::get()->appendRange(&request);
//添加消息头部和消息体的分隔符
request.append("\r\n");
//新建异步处理消息reply
//消息名为'play'
//消息处理者为this也即MyHandler
sp<AMessage> reply = new AMessage('play', this);
//调用mConn->sendRequest发送该请求消息
//异步应答消息reply会被暂时存放在mConn的mPengdingRequests里
//直到对应的服务端的应答消息的到来
//该异步处理消息reply则被发送出去
mConn->sendRequest(request.c_str(), reply);
} else {
//代码执行到这里说明mSetupTracksSuccessful的值不为真
//即带创建track的时候发生了错误
//新建消息reply取消连接
sp<AMessage> reply = new AMessage('disc', this);
mConn->disconnect(reply);
}
break;
}
MyHandler对消息'setu'的处理
最新推荐文章于 2022-08-09 15:19:04 发布