live555 singleStep 分析
来源:互联网 发布:视频慢放软件下载 编辑:程序博客网 时间:2024/06/06 20:13
最近看了看live555代码,看到这部分随手写下来做个记录
1. live555是用的select模型
2. 在处理函数里做了多种操作
处理各个socket上事件,回调函数
处理延迟队列,和队列上的事件,是发送事件,控制发送数据包速度
处理事件响应
个人见解:
感觉这个模型太累了,都是在一个线程里干,效率必定低
void BasicTaskScheduler::SingleStep(unsigned maxDelayTime) { fd_set readSet = fReadSet; // make a copy for this select() call fd_set writeSet = fWriteSet; // ditto fd_set exceptionSet = fExceptionSet; // ditto //DelayInterval const& timeToDelay = fDelayQueue.timeToNextAlarm(); DelayInterval timeToDelay(0, 0); fDelayQueue.timeToNextAlarm(timeToDelay); struct timeval tv_timeToDelay; tv_timeToDelay.tv_sec = timeToDelay.seconds(); tv_timeToDelay.tv_usec = timeToDelay.useconds(); // Very large "tv_sec" values cause select() to fail. // Don't make it any larger than 1 million seconds (11.5 days) const long MAX_TV_SEC = MILLION; if (tv_timeToDelay.tv_sec > MAX_TV_SEC) { tv_timeToDelay.tv_sec = MAX_TV_SEC; } // Also check our "maxDelayTime" parameter (if it's > 0): if (maxDelayTime > 0 && (tv_timeToDelay.tv_sec > (long)maxDelayTime/MILLION || (tv_timeToDelay.tv_sec == (long)maxDelayTime/MILLION &&tv_timeToDelay.tv_usec > (long)maxDelayTime%MILLION))) { tv_timeToDelay.tv_sec = maxDelayTime/MILLION; tv_timeToDelay.tv_usec = maxDelayTime%MILLION; } //unsigned long tickCount = GetTickCount(); // fprintf(stderr, "BasicTaskScheduler::SingleStep() 1, time = %u, %u\n", tv_timeToDelay. tv_sec, tv_timeToDelay.tv_usec); int selectResult = select(fMaxNumSockets, &readSet, &writeSet, &exceptionSet, &tv_timeToDelay); //long long delayTime = tv_timeToDelay.tv_sec*1000+tv_timeToDelay.tv_usec; if (selectResult < 0) {#if defined(__WIN32__) || defined(_WIN32) int err = WSAGetLastError(); // For some unknown reason, select() in Windoze sometimes fails with WSAEINVAL if // it was called with no entries set in "readSet". If this happens, ignore it: if (err == WSAEINVAL && readSet.fd_count == 0) { err = EINTR; // To stop this from happening again, create a dummy socket: int dummySocketNum = socket(AF_INET, SOCK_DGRAM, 0); FD_SET((unsigned)dummySocketNum, &fReadSet); } if (err != EINTR) {#else if (errno != EINTR && errno != EAGAIN) {#endif // Unexpected error - treat this as fatal:#if !defined(_WIN32_WCE) perror("BasicTaskScheduler::SingleStep(): select() fails");#endif //internalError(); fprintf(stderr, "BasicTaskScheduler::SingleStep(): select() fails\n"); fDelayQueue.handleAlarm(); return; } } // END if (selectResult < 0) // Call the handler function for one readable socket: lock(); HandlerIterator iter(*fHandlers); HandlerDescriptor* handler; // To ensure forward progress through the handlers, begin past the last // socket number that we handled: if (fLastHandledSocketNum >= 0) { // 找到上次执行的socket handler的下一个 while ((handler = iter.next()) != NULL) { if (handler->socketNum == fLastHandledSocketNum) break; } if (handler == NULL) { fLastHandledSocketNum = -1; iter.reset(); // start from the beginning instead } } // while ((handler = iter.next()) != NULL) { int sock = handler->socketNum; // alias int resultConditionSet = 0; if (FD_ISSET(sock, &readSet) && FD_ISSET(sock, &fReadSet)/*sanity check*/) resultConditionSet |= SOCKET_READABLE; if (FD_ISSET(sock, &writeSet) && FD_ISSET(sock, &fWriteSet)/*sanity check*/) resultConditionSet |= SOCKET_WRITABLE; if (FD_ISSET(sock, &exceptionSet) && FD_ISSET(sock, &fExceptionSet)/*sanity check*/) resultConditionSet |= SOCKET_EXCEPTION; // fprintf(stderr, "sock: %d, resultConditionSet:%d, %d\n", sock, resultConditionSet, handler->conditionSet); if ((resultConditionSet & handler->conditionSet) != 0 && handler->handlerProc != NULL) { fLastHandledSocketNum = sock; // Note: we set "fLastHandledSocketNum" before calling the handler, // in case the handler calls "doEventLoop()" reentrantly. (*handler->handlerProc)(handler->clientData, resultConditionSet); break; } } // Also handle any newly-triggered event (Note that we do this *after* calling a socket handler, // in case the triggered event handler modifies The set of readable sockets.)
// 待响应事件 if (fTriggersAwaitingHandling != 0) { if (fTriggersAwaitingHandling == fLastUsedTriggerMask) { // Common-case optimization for a single event trigger: fTriggersAwaitingHandling = 0; if (fTriggeredEventHandlers[fLastUsedTriggerNum] != NULL) {(*fTriggeredEventHandlers[fLastUsedTriggerNum])(fTriggeredEventClientDatas[fLastUsedTriggerNum]); } } else { // Look for an event trigger that needs handling (making sure that we make forward progress through all possible triggers): unsigned i = fLastUsedTriggerNum; EventTriggerId mask = fLastUsedTriggerMask; do { i = (i+1)%MAX_NUM_EVENT_TRIGGERS; mask >>= 1; if (mask == 0) mask = 0x80000000; if ((fTriggersAwaitingHandling&mask) != 0) { fTriggersAwaitingHandling &=~ mask; if (fTriggeredEventHandlers[i] != NULL) { (*fTriggeredEventHandlers[i])(fTriggeredEventClientDatas[i]); } fLastUsedTriggerMask = mask; fLastUsedTriggerNum = i; break; } } while (i != fLastUsedTriggerNum); } } // Also handle any delayed event that may have come due. fDelayQueue.handleAlarm();}
阅读全文
0 0
- live555 singleStep 分析
- 【live555】从UsageEnvironment说到doEventLoop中的SingleStep
- live555 分析
- live555 分析
- live555代码分析
- live555 源码分析
- live555 模块分析
- Live555 RTSPServer 分析
- live555 分析- openRtsp
- live555源代码分析
- 【live555】UsageEnvrionment分析
- 【live555】WISInput类分析
- live555 分析- openRtsp
- 【live555】MediaSink类分析
- 【live555】FramedFilter粗浅分析
- 【live555】MPEGVideoStreamFramer简要分析
- 【live555】OnDemandServerMediaSubsession 粗浅分析
- 【live555】OutPacketBuffer粗浅分析
- javascript 使用btoa和atob来进行Base64转码和解码
- MySQL查询指定字段
- 数据结构-算法-时间复杂度计算
- mybatis一对多sql语句:
- Win32API学习笔记第八章
- live555 singleStep 分析
- JS中全局函数与函数重载常用基础知识
- 一款APP,从设计稿到切图(Android篇)
- 微信文件找回
- 深度学习五:tensorboard使用记录(windows)
- 【大话数据结构】线性表:顺序表和链表
- SVN在Android Studio中的配置
- EditText中onEditorAction监听事件执行两次
- Java反射机制详解