EventScheduler包含三种Event的处理方法。
1.TriggerEvent ,从它的的callback函数可以看出,主要处理RtspServer::cbCloseConnect关闭连接
2.TimerEvent,服务于流媒体的sink实例发送视频
3.IOEvent. 通过select poller处理socketfd连接事件
Windows不能使用select poller来调度定时器事件,而linux却可以。
下面函数将TimerEvent加入了调度器:
void Sink::runEvery(int interval){
mTimerId = mEnv->scheduler()->addTimedEventRunEvery(mTimerEvent, interval);
}
TimerMananger的核心函数是handleRead:
这个核心函数会调用timer.handleEvent函数:bool timerEventIsStop = timer.handleEvent();
void TimerManager::readCallback(void arg) {
TimerManager timerManager = (TimerManager*)arg;
timerManager->handleRead();
}
void TimerManager::handleRead() {
//LOGI("mTimers.size()=%d,mEvents.size()=%d",mTimers.size(),mEvents.size());
Timer::Timestamp timestamp = Timer::getCurTime();
if (!mTimers.empty() && !mEvents.empty()) {
std::multimap<Timer::Timestamp, Timer>::iterator it = mEvents.begin();
Timer timer = it->second;
int expire = timer.mTimestamp - timestamp;
//LOGI("timestamp=%d,mTimestamp=%d,expire=%d,timeInterval=%d", timestamp, timer.mTimestamp, expire, timer.mTimeInterval);
if (timestamp > timer.mTimestamp || expire == 0) {
bool timerEventIsStop = timer.handleEvent();
mEvents.erase(it);
if (timer.mRepeat) {
if (timerEventIsStop) {
mTimers.erase(timer.mTimerId);
}else {
timer.mTimestamp = timestamp + timer.mTimeInterval;
mEvents.insert(std::make_pair(timer.mTimestamp, timer));
}
}
else {
mTimers.erase(timer.mTimerId);
}
}
}
modifyTimeout();
}
bool Timer::handleEvent()
{
if (!mTimerEvent) {
return false;
}
return mTimerEvent->handleEvent();
}
bool TimerEvent::handleEvent()
{
if (mIsStop) {
return mIsStop;
}
if(mTimeoutCallback)
mTimeoutCallback(mArg);
return mIsStop;
}
Sink的构造函数会调用setTimeoutCallback函数,设置timeout的回调函数cbTimeout。
void setTimeoutCallback(EventCallback cb) { mTimeoutCallback = cb; }
Sink::Sink(UsageEnvironment* env, MediaSource* mediaSource, int payloadType) :
mMediaSource(mediaSource),
mEnv(env),
mCsrcLen(0),
mExtension(0),
mPadding(0),
mVersion(RTP_VESION),
mPayloadType(payloadType),
mMarker(0),
mSeq(0),
mSSRC(rand()),
mTimestamp(0),
mTimerId(0),
mSessionSendPacket(NULL),
mArg1(NULL),
mArg2(NULL)
{
LOGI("Sink()");
mTimerEvent = TimerEvent::createNew(this);
mTimerEvent->setTimeoutCallback(cbTimeout);
}
void Sink::cbTimeout(void arg) {
Sink sink = (Sink*)arg;
sink->handleTimeout();
}
void Sink::handleTimeout() {
MediaFrame* frame = mMediaSource->getFrameFromOutputQueue();
if (!frame) {
return;
}
this->sendFrame(frame);// 由具体子类实现发送逻辑
mMediaSource->putFrameToInputQueue(frame);//将使用过的frame插入输入队列,插入输入队列以后,加入一个子线程task,从文件中读取数据再次将输入写入到frame
}
Sink的下面函数会把mTimerEvent注册到scheduler调度器:
void Sink::runEvery(int interval){
mTimerId = mEnv->scheduler()->addTimedEventRunEvery(mTimerEvent, interval);
}
:
从下图的引用看出,只有RtspServer和TcpConnection调用了IOEvent的构造函数,来构造IOEvent.
:
RtspServer的handleRead函数收到有客户端连接进来后,会建立RtspConnection的实例。RtspConnection类是继承于TcpConnction类。
然后mConnMap.insert(std::make_pair(clientFd, conn));会将改客户端的id和连接信息,插入到mConnMap中。
RtspConnection调用TcpConnection构造函数
TcpConnection构造函数产生一个IOEvent,并把这个IOEvent加入到调度器scheduler中。
RtspServer start函数和TcpConnection的构造函数中会增加IOEvent.
RtspServer和TcpConnection的析构函数中会removeIOEvent.
selectpoller继承与顶级父类poller:
class SelectPoller : public Poller
virtual bool addIOEvent(IOEvent* event) = 0;
virtual bool updateIOEvent(IOEvent* event) = 0;
virtual bool removeIOEvent(IOEvent* event) = 0;
virtual void handleEvent() = 0;
selectpoller类实现了顶级父类的纯虚函数:
virtual bool addIOEvent(IOEvent* event);
virtual bool updateIOEvent(IOEvent* event);
virtual bool removeIOEvent(IOEvent* event);
virtual void handleEvent();
RtspServer::RtspServer
中创建了TcpSock IO Event
mFd = sockets::createTcpSock();
mAcceptIOEvent = IOEvent::createNew(mFd, this);
TcpConnection::TcpConnection
中创建了clientFd IO Event
mClientIOEvent = IOEvent::createNew(clientFd, this);
void RtspServer::handleRead()
->tspConnection* conn = RtspConnection::createNew(this, clientFd);
->RtspConnection::RtspConnection(RtspServer* rtspServer, int clientFd)
->class RtspConnection : public TcpConnection
RtspConnection继承于TcpConnection。
TcpConnection(UsageEnvironment* env, int clientFd);
TcpConnection的构造函数中中创建了clientFd IO Event