/* 用当前RTSPSession构造一个OSRef实例, 在RTPSession Map(Hash表)中注册并加入该引用OSRef元(其key值唯一), 同时更新qtssSvrClientSessions的属性,及QTSServerInterface中的总RTPSession数 */ QTSS_Error RTPSession::Activate(const StrPtrLen& inSessionID) { //Set the session ID for this session /* 用入参配置fRTSPSessionIDBuf的值(是C-String) */ Assert(inSessionID.Len <= QTSS_MAX_SESSION_ID_LENGTH); ::memcpy(fRTSPSessionIDBuf, inSessionID.Ptr, inSessionID.Len); fRTSPSessionIDBuf[inSessionID.Len] = '\0'; /* 用C-String的fRTSPSessionIDBuf设置qtssCliSesRTSPSessionID的属性值 */ this->SetVal(qtssCliSesRTSPSessionID, &fRTSPSessionIDBuf[0], inSessionID.Len); /* 用qtssCliSesRTSPSessionID的属性值来得到一个RTPSession Map的引用OSRef元 */ fRTPMapElem.Set(*this->GetValue(qtssCliSesRTSPSessionID), this); /* 获取服务器接口 */ QTSServerInterface* theServer = QTSServerInterface::GetServer(); //Activate puts the session into the RTPSession Map /* 在RTPSession Map(Hash表)中注册并加入一个引用OSRef,若字符串标识唯一,就能成功返回OS_NoErr;若有一个相同key值的元素,就返回错误EPERM */ QTSS_Error err = theServer->GetRTPSessionMap()->Register(&fRTPMapElem); //若有同名键值,立即返回 if (err == EPERM) return err; /* 确保key值唯一 */ Assert(err == QTSS_NoErr); // // Adding this session into the qtssSvrClientSessions attr and incrementing the number of sessions must be atomic /* 锁定服务器对象 */ OSMutexLocker locker(theServer->GetMutex()); // // Put this session into the qtssSvrClientSessions attribute of the server #if DEBUG Assert(theServer->GetNumValues(qtssSvrClientSessions) == theServer->GetNumRTPSessions());//确保属性qtssSvrClientSessions中的RTPSession个数和服务器中实际的个数相同 #endif /* 设置qtssSvrClientSessions的第GetNumRTPSessions()个RTPSession的属性 */ RTPSession* theSession = this; err = theServer->SetValue(qtssSvrClientSessions, theServer->GetNumRTPSessions(), &theSession, sizeof(theSession), QTSSDictionary::kDontObeyReadOnly); Assert(err == QTSS_NoErr); #if DEBUG fActivateCalled = true; #endif /* 及时更新QTSServerInterface中的总RTPSession数 */ QTSServerInterface::GetServer()->IncrementTotalRTPSessions(); return QTSS_NoErr; }
QTSS_Error RTPSession::Activate(const StrPtrLen& inSessionID) { //Set the session ID for this session Assert(inSessionID.Len <= QTSS_MAX_SESSION_ID_LENGTH); ::memcpy(fRTSPSessionIDBuf, inSessionID.Ptr, inSessionID.Len); fRTSPSessionIDBuf[inSessionID.Len] = '\0'; this->SetVal(qtssCliSesRTSPSessionID, &fRTSPSessionIDBuf[0], inSessionID.Len); fRTPMapElem.Set(*this->GetValue(qtssCliSesRTSPSessionID), this); QTSServerInterface* theServer = QTSServerInterface::GetServer(); //Activate puts the session into the RTPSession Map QTSS_Error err = theServer->GetRTPSessionMap()->Register(&fRTPMapElem); if (err == EPERM) return err; Assert(err == QTSS_NoErr); // // Adding this session into the qtssSvrClientSessions attr and incrementing the number of sessions must be atomic OSMutexLocker locker(theServer->GetMutex()); // // Put this session into the qtssSvrClientSessions attribute of the server #if DEBUG Assert(theServer->GetNumValues(qtssSvrClientSessions) == theServer->GetNumRTPSessions()); #endif RTPSession* theSession = this; err = theServer->SetValue(qtssSvrClientSessions, theServer->GetNumRTPSessions(), &theSession, sizeof(theSession), QTSSDictionary::kDontObeyReadOnly); Assert(err == QTSS_NoErr); #if DEBUG fActivateCalled = true; #endif QTSServerInterface::GetServer()->IncrementTotalRTPSessions(); return QTSS_NoErr; }
RTPSession::~RTPSession() { // Delete all the streams RTPStream** theStream = NULL; UInt32 theLen = 0; /* 假如预设值能打印RUDP信息 */ if (QTSServerInterface::GetServer()->GetPrefs()->GetReliableUDPPrintfsEnabled()) { SInt32 theNumLatePacketsDropped = 0;/* 丢弃延迟包个数 */ SInt32 theNumResends = 0; /* 重传包个数 */ /* 遍历该RTPSession的每个RTPStream,计算丢弃的过时包总数和重传包总数 */ for (int x = 0; this->GetValuePtr(qtssCliSesStreamObjects, x, (void**)&theStream, &theLen) == QTSS_NoErr; x++) { Assert(theStream != NULL); Assert(theLen == sizeof(RTPStream*)); if (*theStream != NULL) { /* 计算丢弃的过时包总数 */ theNumLatePacketsDropped += (*theStream)->GetStalePacketsDropped(); /* 得到重传包总数 */ theNumResends += (*theStream)->GetResender()->GetNumResends(); } } /* 得到客户端请求播放文件的Full URL */ char* theURL = NULL; (void)this->GetValueAsString(qtssCliSesFullURL, 0, &theURL); Assert(theURL != NULL); /* 获得RTPBandwidthTracker类 */ RTPBandwidthTracker* tracker = this->GetBandwidthTracker(); qtss_printf("Client complete. URL: %s.\n",theURL); qtss_printf("Max congestion window: %ld. Min congestion window: %ld. Avg congestion window: %ld\n", tracker->GetMaxCongestionWindowSize(), tracker->GetMinCongestionWindowSize(), tracker->GetAvgCongestionWindowSize()); qtss_printf("Max RTT: %ld. Min RTT: %ld. Avg RTT: %ld\n", tracker->GetMaxRTO(), tracker->GetMinRTO(), tracker->GetAvgRTO()); qtss_printf("Num resends: %ld. Num skipped frames: %ld. Num late packets dropped: %ld\n", theNumResends, this->GetFramesSkipped(), theNumLatePacketsDropped); delete [] theURL; } /* 遍历该RTPSession的每个RTPStream,逐一删除它们 */ for (int x = 0; this->GetValuePtr(qtssCliSesStreamObjects, x, (void**)&theStream, &theLen) == QTSS_NoErr; x++) { Assert(theStream != NULL); Assert(theLen == sizeof(RTPStream*)); if (*theStream != NULL) delete *theStream; } /* 获取服务器接口类,逐一将该RTPSession从qtssSvrClientSessions属性中删去 */ QTSServerInterface* theServer = QTSServerInterface::GetServer(); { OSMutexLocker theLocker(theServer->GetMutex()); RTPSession** theSession = NULL; // Remove this session from the qtssSvrClientSessions attribute UInt32 y = 0; for ( ; y < theServer->GetNumRTPSessions(); y++) { QTSS_Error theErr = theServer->GetValuePtr(qtssSvrClientSessions, y, (void**)&theSession, &theLen, true); Assert(theErr == QTSS_NoErr); if (*theSession == this) { theErr = theServer->RemoveValue(qtssSvrClientSessions, y, QTSSDictionary::kDontObeyReadOnly); break; } } Assert(y < theServer->GetNumRTPSessions()); theServer->AlterCurrentRTPSessionCount(-1); if (!fIsFirstPlay) // The session was started playing (the counter ignores additional pause-play changes while session is active) theServer->AlterRTPPlayingSessions(-1); } //we better not be in the RTPSessionMap anymore! #if DEBUG Assert(!fRTPMapElem.IsInTable()); StrPtrLen theRTSPSessionID(fRTSPSessionIDBuf,sizeof(fRTSPSessionIDBuf)); /* 从RTPSession Map中删去它们 */ OSRef* theRef = QTSServerInterface::GetServer()->GetRTPSessionMap()->Resolve(&theRTSPSessionID); Assert(theRef == NULL); #endif }