由main函数开始分析
//没有传入任何参数
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
BasicTaskScheduler* BasicTaskScheduler::createNew(unsigned maxSchedulerGranularity) {
return new BasicTaskScheduler(maxSchedulerGranularity);
}
<pre name="code" class="cpp">//maxSchedulerGranularity =10000 默认值,最大的调度时间间隔
//fMaxNumSockets = 0
BasicTaskScheduler::BasicTaskScheduler(unsigned maxSchedulerGranularity)
: fMaxSchedulerGranularity(maxSchedulerGranularity), fMaxNumSockets(0)
#if defined(__WIN32__) || defined(_WIN32)
, fDummySocketNum(-1)
#endif
{
//set一种数据结构,long类型
FD_ZERO(&fReadSet);//清空fReadSet集合
FD_ZERO(&fWriteSet);//清空fExceptionSet集合
FD_ZERO(&fExceptionSet);//清空fExceptionSet集合
if (maxSchedulerGranularity > 0) schedulerTickTask(); // ensures that we handle events frequently
}
//schedulerTickTask函数
void BasicTaskScheduler::schedulerTickTask() {
scheduleDelayedTask(fMaxSchedulerGranularity, schedulerTickTask, this);
}
void BasicTaskScheduler::schedulerTickTask(void* clientData) {
((BasicTaskScheduler*)clientData)->schedulerTickTask();
}
//microseconds = 10000
TaskToken BasicTaskScheduler0::scheduleDelayedTask(int64_t microseconds,
TaskFunc* proc,
void* clientData) {
if (microseconds < 0) microseconds = 0;
//timeToDelay(0,10000)秒、微秒
//fTv.tv_sec= 0, fTv.tv_usec= 10000
DelayInterval timeToDelay((long)(microseconds/1000000), (long)(microseconds%1000000));
AlarmHandler* alarmHandler = new AlarmHandler(proc, clientData, timeToDelay);
//alarmHandler->fProc =proc = schedulerTickTask(void* clientData) clientData = scheduler
//alarmHandler->DelayQueueEntry = timeToDelay
//把函数schedulerTickTask(void* clientData)注册到了alarmHandler ,然后把新建alarmHandler插入到调度器中。
fDelayQueue.addEntry(alarmHandler);
return (void*)(alarmHandler->token());
}
// 把新的任务作为新的节点插入到调度队列入口
void DelayQueue::addEntry(DelayQueueEntry* newEntry) {
synchronize();
DelayQueueEntry* cur = head();
while (newEntry->fDeltaTimeRemaining >= cur->fDeltaTimeRemaining) {
newEntry->fDeltaTimeRemaining -= cur->fDeltaTimeRemaining;
cur = cur->fNext;
}
cur->fDeltaTimeRemaining -= newEntry->fDeltaTimeRemaining;
// Add "newEntry" to the queue, just before "cur":
newEntry->fNext = cur;
newEntry->fPrev = cur->fPrev;
cur->fPrev = newEntry->fPrev->fNext = newEntry;
}
DelayInterval operator-(const Timeval& arg1, const Timeval& arg2) {
time_base_seconds secs = arg1.seconds() - arg2.seconds();
time_base_seconds usecs = arg1.useconds() - arg2.useconds();
if ((int)usecs < 0) {
usecs += MILLION;
--secs;
}
if ((int)secs < 0)
return DELAY_ZERO;
else
return DelayInterval(secs, usecs);
}
</pre><pre code_snippet_id="634470" snippet_file_name="blog_20150402_10_2569867" name="code" class="cpp">//========================================================================================
UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);
/**********************************************************************************
BasicUsageEnvironment::BasicUsageEnvironment(TaskScheduler& taskScheduler)
: BasicUsageEnvironment0(taskScheduler) {
#if defined(__WIN32__) || defined(_WIN32)
if (!initializeWinsockIfNecessary()) {
setResultErrMsg("Failed to initialize 'winsock': ");
reportBackgroundError();
internalError();
}
#endif
}
#define RESULT_MSG_BUFFER_MAX 1000
BasicUsageEnvironment::createNew(TaskScheduler& taskScheduler) {
return new BasicUsageEnvironment(taskScheduler);
}
BasicUsageEnvironment0::BasicUsageEnvironment0(TaskScheduler& taskScheduler)
: UsageEnvironment(taskScheduler),
fBufferMaxSize(RESULT_MSG_BUFFER_MAX) {
reset();
}
//fBufferMaxSize = 1000
void BasicUsageEnvironment0::reset() {
fCurBufferSize = 0;
fResultMsgBuffer[fCurBufferSize] = '\0';
}
</pre><pre code_snippet_id="634470" snippet_file_name="blog_20150402_18_8235671" name="code" class="cpp">UsageEnvironment::UsageEnvironment(TaskScheduler& scheduler)
: liveMediaPriv(NULL), groupsockPriv(NULL), fScheduler(scheduler) {
}
//env->liveMediaPriv = NULL env->groupsockPriv =NULL env->fScheduler = scheduler
// TaskScheduler* scheduler = BasicTaskScheduler::createNew(); 第一句
//========================================================================================================
//假设只有1个RTSP客户端
//arv,
//输入命令为:./testRTDPClient rtsp://192.168.2.1:8080/123456.sdp
// argv[1] = rtsp://192.168.2.1:8080/123456.sdp
//argv[0] = ./testRTDPClient
for (int i = 1; i <= argc-1; ++i) {
openURL(*env, argv[0], argv[i]);
}
</pre><pre code_snippet_id="634470" snippet_file_name="blog_20150402_20_5623429" name="code" class="cpp">void openURL(UsageEnvironment& env, char const* progName, char const* rtspURL) {
// Begin by creating a "RTSPClient" object. Note that there is a separate "RTSPClient" object for each stream that we wish
// to receive (even if more than stream uses the same "rtsp://" URL).
RTSPClient* rtspClient = ourRTSPClient::createNew(env, rtspURL, RTSP_CLIENT_VERBOSITY_LEVEL, progName);
if (rtspClient == NULL) {
env << "Failed to create a RTSP client for URL \"" << rtspURL << "\": " << env.getResultMsg() << "\n";
return;
}
++rtspClientCount;
// Next, send a RTSP "DESCRIBE" command, to get a SDP description for the stream.
// Note that this command - like all RTSP commands - is sent asynchronously; we do not block, waiting for a response.
// Instead, the following function call returns immediately, and we handle the RTSP response later, from within the event loop:
rtspClient->sendDescribeCommand(continueAfterDESCRIBE);
}
</pre><pre code_snippet_id="634470" snippet_file_name="blog_20150402_22_4930015" name="code" class="cpp">ourRTSPClient* ourRTSPClient::createNew(UsageEnvironment& env, char const* rtspURL,
int verbosityLevel, char const* applicationName, portNumBits tunnelOverHTTPPortNum) {
return new ourRTSPClient(env, rtspURL, verbosityLevel, applicationName, tunnelOverHTTPPortNum);
}
ourRTSPClient::ourRTSPClient(UsageEnvironment& env, char const* rtspURL,
<span style="white-space:pre"> </span> int verbosityLevel, char const* applicationName, portNumBits tunnelOverHTTPPortNum)
: RTSPClient(env,rtspURL, verbosityLevel, applicationName, tunnelOverHTTPPortNum, -1) {
}
</pre><pre code_snippet_id="634470" snippet_file_name="blog_20150402_24_332906" name="code" class="cpp">RTSPClient::RTSPClient(UsageEnvironment& env, char const* rtspURL,
int verbosityLevel, char const* applicationName,
portNumBits tunnelOverHTTPPortNum, int socketNumToServer)
: Medium(env),
/*
1、
rtspClient->fEnviron = env
rtspClient->fNextTask = NULL
2、
Medium::Medium(UsageEnvironment& env): fEnviron(env), fNextTask(NULL) {
// First generate a name for the new medium:
MediaLookupTable::ourMedia(env)->generateNewName(fMediumName, mediumNameMaxLen);
env.setResultMsg(fMediumName);
// Then add it to our table:
MediaLookupTable::ourMedia(env)->addNew(this, fMediumName);
}
3、
MediaLookupTable* MediaLookupTable::ourMedia(UsageEnvironment& env) {
_Tables* ourTables = _Tables::getOurTables(env);
if (ourTables->mediaTable == NULL) {
// Create a new table to record the media that are to be created in
// this environment:
ourTables->mediaTable = new MediaLookupTable(env);
}
return ourTables->mediaTable;
}
4、
_Tables* _Tables::getOurTables(UsageEnvironment& env, Boolean createIfNotPresent) {
if (env.liveMediaPriv == NULL && createIfNotPresent) {
env.liveMediaPriv = new _Tables(env); // The first time to excute this line
}
return (_Tables*)(env.liveMediaPriv);
}
_Tables::_Tables(UsageEnvironment& env)
: mediaTable(NULL), socketTable(NULL), fEnv(env) {
}
5、
env->liveMediaPriv = new _Tables(env)
env->liveMediaPriv->fEnv=env
env->liveMediaPriv->mediaTable = NULL
env->liveMediaPriv->socketTable = NULL
ourTables = env->liveMediaPriv
5、
create hash table!!!
int const STRING_HASH_KEYS = 0;
env->mediaTable= new MediaLookupTable()
ourTables->mediaTable->fEnv=env
ourTables->mediaTable->fTable = new HashTable(STRING_HASH_KEYS)
ourTables->mediaTable->fNameGenerator=0
MediaLookupTable::MediaLookupTable(UsageEnvironment& env)
: fEnv(env), fTable(HashTable::create(STRING_HASH_KEYS)), fNameGenerator(0) {
}
class BasicHashTable: public HashTable
7、
return env->liveMediaPriv->mediaTable
8、
void MediaLookupTable::generateNewName(char* mediumName,unsigned )
{
// We should really use snprintf() here, but not all systems have it
sprintf(mediumName, "liveMedia%d", fNameGenerator++);
}
一个 RtspClient 客户端对应一个媒体名字为liveMediax,x=0、1 、2、3...
这里只有一个客户端:故:liveMedia0,即:Medium->fMediumName = liveMedia0
9、
env.setResultMsg(fMediumName);
void BasicUsageEnvironment0::setResultMsg(MsgString msg) {
reset();
appendToResultMsg(msg);
}
fResultMsgBuffe[] = fMediumName = "liveMedia0"
fCurBufferSize = strlen("liveedia0")
10、
MediaLookupTable::ourMedia(env)->addNew(this, fMediumName);
<==>(ourTables->mediaTable)->addNew(this, fMediumName);
<==>((env->liveMediaPriv)->mediaTable)->addNew(this, fMediumName);
11、
void MediaLookupTable::addNew(Medium* medium, char* mediumName) {
fTable->Add(mediumName, (void*)medium);
}
((ourTables->mediaTable)->fTable)->Add(mediumName, (void*)medium);
12、(一个Medium ,一个名字)插入到 hash table中并映射一个Entry给他
void* BasicHashTable::Add(char const* key, void* value) {
void* oldValue;
unsigned index;
TableEntry* entry = lookupKey(key, index);
if (entry != NULL) {
// There's already an item with this key
oldValue = entry->value;
} else {
// There's no existing entry; create a new one:
entry = insertNewEntry(index, key);
oldValue = NULL;
}
entry->value = value;
// If the table has become too large, rebuild it with more buckets:
if (fNumEntries >= fRebuildSize) rebuild();
return oldValue;
}
*/