Live555源码阅读之Mediaserver总体预览
2015-10-10 13:07
288 查看
这篇博文是随手记录,思路稍显紊乱,仅供自己记录参阅,后续如若有时间详细分析与学习
rtspserver创建及工作流程分析
rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);//构造rtspServer
DynamicRTSPServer ---> //继承
RTSPServerSupportingHTTPStreaming --->
RTSPServer --->
GenericMediaServer --->
Medium
主要构造工作
GenericMediaServer::GenericMediaServer(UsageEnvironment& env, int ourSocket,
Port ourPort,unsigned reclamationSeconds)
{
...
ignoreSigPipeOnSocket(fServerSocket);
// Arrange to handle connections from others:
env.taskScheduler().turnOnBackgroundReadHandling(fServerSocket, incomingConnectionHandler, this);
}
turnOnBackgroundReadHandling --->
BasicTaskScheduler::setBackgroundHandling(socketNum, SOCKET_READABLE, handlerProc, clientData) --->
fHandlers->assignHandler(socketNum, conditionSet, handlerProc, clientData)
//这里说明一下,HandlerSet &fHandlers,负责注册基于socketNum的读写以及异常的事件处理
//维护一个HandlerDescriptor类的双向链表,包含了socketNum和对应的handlerProc处理方法
BasicTaskScheduler::BasicTaskScheduler(unsigned maxSchedulerGranularity)
: fMaxSchedulerGranularity(maxSchedulerGranularity), fMaxNumSockets(0)
#if defined(__WIN32__) || defined(_WIN32)
, fDummySocketNum(-1)
#endif
{
FD_ZERO(&fReadSet);
FD_ZERO(&fWriteSet);
FD_ZERO(&fExceptionSet);
if (maxSchedulerGranularity > 0) schedulerTickTask(); // ensures that we handle events frequently
}
//BasicTaskScheduler类继承自BasicTaskScheduler0,初始化读写异常文件描述符集,调用schedulerTickTask,这个函数对应的处理函数是自身,反复调用
BasicTaskScheduler0::BasicTaskScheduler0()
: fLastHandledSocketNum(-1), fTriggersAwaitingHandling(0), fLastUsedTriggerMask(1), fLastUsedTriggerNum(MAX_NUM_EVENT_TRIGGERS-1) {
fHandlers = new HandlerSet;
for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
fTriggeredEventHandlers[i] = NULL;
fTriggeredEventClientDatas[i] = NULL;
}
}
//BasicTaskScheduler0构造函数创建了用于存储socket事件处理映射的HandlerSet,并初始化触发事件数组
主函数最终调用env->taskScheduler().doEventLoop();进入事件处理循环(主循环),等待客户端连接等一系列操作
/////////////////////////////////////////////////////////////////////////////////
服务器接收到客户端连接请求回调函数incomingConnectionHandlerOnSocket(fServerSocket) --->
int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen) &&&
(void)createNewClientConnection(clientSocket, clientAddr) --->
RTSPServer::RTSPClientConnection::RTSPClientConnection(RTSPServer& ourServer, int clientSocket, struct sockaddr_in clientAddr)
: GenericMediaServer::ClientConnection(ourServer, clientSocket, clientAddr),
fOurRTSPServer(ourServer), fClientInputSocket(fOurSocket), fClientOutputSocket(fOurSocket),
fIsActive(True), fRecursionCount(0), fOurSessionCookie(NULL) {
resetRequestBuffer();
}
调用GenericMediaServer::ClientConnection的构造函数
GenericMediaServer::ClientConnection::ClientConnection(GenericMediaServer& ourServer, int clientSocket, struct sockaddr_in clientAddr)
: fOurServer(ourServer), fOurSocket(clientSocket), fClientAddr(clientAddr) {
// Add ourself to our 'client connections' table:
fOurServer.fClientConnections->Add((char const*)this, this);
// Arrange to handle incoming requests:
resetRequestBuffer();
envir().taskScheduler().setBackgroundHandling(fOurSocket, SOCKET_READABLE|SOCKET_EXCEPTION, incomingRequestHandler, this);
//将客户端socket加入后台处理调度程序,绑定回调处理函数incomingRequestHandler,当客户端有数据可读或异常的时候
}
/////////////////////////////////////////////////////////////////////////////////
客户端请求处理回调函数incomingRequestHandler
void GenericMediaServer::ClientConnection::incomingRequestHandler() {
struct sockaddr_in dummy; // 'from' address, meaningless in this case
int bytesRead = readSocket(envir(), fOurSocket, &fRequestBuffer[fRequestBytesAlreadySeen], fRequestBufferBytesLeft, dummy);
handleRequestBytes(bytesRead);
}
其中readSocket调用recvfrom将接收到的数据存储于fRequestBuffer[fRequestBytesAlreadySeen],
而handleRequestBytes是最核心的解析请求并做出相应操作的函数,星级5颗星。
下面我们来看一下handleRequestBytes函数,它是GenericMediaServer类中声明的虚函数,在RTSPServer中实现
--->
.......//一系列前序操作
handleCmd_PLAY --->
OnDemandServerMediaSubsession::startStream --->
streamState->startPlaying --->
fRTPSink->startPlaying --->
continuePlaying() --->这里关注h264--->
H264or5VideoRTPSink::continuePlaying() ---> 到父类 --->
MultiFramedRTPSink::continuePlaying() --->
buildAndSendPacket(True) --->
设置rtp头 && packFrame() --->
fSource->getNextFrame(fOutBuf->curPtr(), fOutBuf->totalBytesAvailable(), afterGettingFrame, this, ourHandleClosure, this) --->
afterGettingFrame 作为回调函数,this 作为数据指针传入回调函数,进而调用类内函数afterGettingFrame1 --->
sendPacketIfNecessary() ---> 发送完成后调用 --->
envir().taskScheduler().scheduleDelayedTask(uSecondsToGo, (TaskFunc*)sendNext, this); ---> 加入 sendNext任务
sendNext --->
sink->buildAndSendPacket(False);//与上面的buildAndSendPacket(True)构成循环发送体系,使视频流持续发送,这里的false,ture仅代表是否为第一个包.
至此大体流程走完,初学,后续会细读代码。
rtspserver创建及工作流程分析
rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);//构造rtspServer
DynamicRTSPServer ---> //继承
RTSPServerSupportingHTTPStreaming --->
RTSPServer --->
GenericMediaServer --->
Medium
主要构造工作
GenericMediaServer::GenericMediaServer(UsageEnvironment& env, int ourSocket,
Port ourPort,unsigned reclamationSeconds)
{
...
ignoreSigPipeOnSocket(fServerSocket);
// Arrange to handle connections from others:
env.taskScheduler().turnOnBackgroundReadHandling(fServerSocket, incomingConnectionHandler, this);
}
turnOnBackgroundReadHandling --->
BasicTaskScheduler::setBackgroundHandling(socketNum, SOCKET_READABLE, handlerProc, clientData) --->
fHandlers->assignHandler(socketNum, conditionSet, handlerProc, clientData)
//这里说明一下,HandlerSet &fHandlers,负责注册基于socketNum的读写以及异常的事件处理
//维护一个HandlerDescriptor类的双向链表,包含了socketNum和对应的handlerProc处理方法
BasicTaskScheduler::BasicTaskScheduler(unsigned maxSchedulerGranularity)
: fMaxSchedulerGranularity(maxSchedulerGranularity), fMaxNumSockets(0)
#if defined(__WIN32__) || defined(_WIN32)
, fDummySocketNum(-1)
#endif
{
FD_ZERO(&fReadSet);
FD_ZERO(&fWriteSet);
FD_ZERO(&fExceptionSet);
if (maxSchedulerGranularity > 0) schedulerTickTask(); // ensures that we handle events frequently
}
//BasicTaskScheduler类继承自BasicTaskScheduler0,初始化读写异常文件描述符集,调用schedulerTickTask,这个函数对应的处理函数是自身,反复调用
BasicTaskScheduler0::BasicTaskScheduler0()
: fLastHandledSocketNum(-1), fTriggersAwaitingHandling(0), fLastUsedTriggerMask(1), fLastUsedTriggerNum(MAX_NUM_EVENT_TRIGGERS-1) {
fHandlers = new HandlerSet;
for (unsigned i = 0; i < MAX_NUM_EVENT_TRIGGERS; ++i) {
fTriggeredEventHandlers[i] = NULL;
fTriggeredEventClientDatas[i] = NULL;
}
}
//BasicTaskScheduler0构造函数创建了用于存储socket事件处理映射的HandlerSet,并初始化触发事件数组
主函数最终调用env->taskScheduler().doEventLoop();进入事件处理循环(主循环),等待客户端连接等一系列操作
/////////////////////////////////////////////////////////////////////////////////
服务器接收到客户端连接请求回调函数incomingConnectionHandlerOnSocket(fServerSocket) --->
int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen) &&&
(void)createNewClientConnection(clientSocket, clientAddr) --->
RTSPServer::RTSPClientConnection::RTSPClientConnection(RTSPServer& ourServer, int clientSocket, struct sockaddr_in clientAddr)
: GenericMediaServer::ClientConnection(ourServer, clientSocket, clientAddr),
fOurRTSPServer(ourServer), fClientInputSocket(fOurSocket), fClientOutputSocket(fOurSocket),
fIsActive(True), fRecursionCount(0), fOurSessionCookie(NULL) {
resetRequestBuffer();
}
调用GenericMediaServer::ClientConnection的构造函数
GenericMediaServer::ClientConnection::ClientConnection(GenericMediaServer& ourServer, int clientSocket, struct sockaddr_in clientAddr)
: fOurServer(ourServer), fOurSocket(clientSocket), fClientAddr(clientAddr) {
// Add ourself to our 'client connections' table:
fOurServer.fClientConnections->Add((char const*)this, this);
// Arrange to handle incoming requests:
resetRequestBuffer();
envir().taskScheduler().setBackgroundHandling(fOurSocket, SOCKET_READABLE|SOCKET_EXCEPTION, incomingRequestHandler, this);
//将客户端socket加入后台处理调度程序,绑定回调处理函数incomingRequestHandler,当客户端有数据可读或异常的时候
}
/////////////////////////////////////////////////////////////////////////////////
客户端请求处理回调函数incomingRequestHandler
void GenericMediaServer::ClientConnection::incomingRequestHandler() {
struct sockaddr_in dummy; // 'from' address, meaningless in this case
int bytesRead = readSocket(envir(), fOurSocket, &fRequestBuffer[fRequestBytesAlreadySeen], fRequestBufferBytesLeft, dummy);
handleRequestBytes(bytesRead);
}
其中readSocket调用recvfrom将接收到的数据存储于fRequestBuffer[fRequestBytesAlreadySeen],
而handleRequestBytes是最核心的解析请求并做出相应操作的函数,星级5颗星。
下面我们来看一下handleRequestBytes函数,它是GenericMediaServer类中声明的虚函数,在RTSPServer中实现
--->
.......//一系列前序操作
handleCmd_PLAY --->
OnDemandServerMediaSubsession::startStream --->
streamState->startPlaying --->
fRTPSink->startPlaying --->
continuePlaying() --->这里关注h264--->
H264or5VideoRTPSink::continuePlaying() ---> 到父类 --->
MultiFramedRTPSink::continuePlaying() --->
buildAndSendPacket(True) --->
设置rtp头 && packFrame() --->
fSource->getNextFrame(fOutBuf->curPtr(), fOutBuf->totalBytesAvailable(), afterGettingFrame, this, ourHandleClosure, this) --->
afterGettingFrame 作为回调函数,this 作为数据指针传入回调函数,进而调用类内函数afterGettingFrame1 --->
sendPacketIfNecessary() ---> 发送完成后调用 --->
envir().taskScheduler().scheduleDelayedTask(uSecondsToGo, (TaskFunc*)sendNext, this); ---> 加入 sendNext任务
sendNext --->
sink->buildAndSendPacket(False);//与上面的buildAndSendPacket(True)构成循环发送体系,使视频流持续发送,这里的false,ture仅代表是否为第一个包.
至此大体流程走完,初学,后续会细读代码。
相关文章推荐
- C++类&对象
- crontab演出newLISP脚本设置环境变量
- linux启动和关闭防火墙命令
- IOS delegate注册推送
- spring整合cxf方式发布的rest webservice,调用接口
- linux端口开放
- 六,变量命名
- IOS横屏事件
- x-code7遇到问题
- Windows中编译Lua源码
- linux常用命令
- Eclipse存console的log
- 关于Git和Github你不知道的十件事
- Windows、Linux -- 远程登录、文件传输、文件共享
- nginx安装-del
- linux服务器su之后变成bash-4.1#
- 数据结构之链队列
- 黑马程序员-------C中的运算符大集合
- GTK+浅谈之十四Glade使用
- IOS汉字排序