Live555源码阅读之Mediaserver总体预览

这篇博文是随手记录,思路稍显紊乱,仅供自己记录参阅,后续如若有时间详细分析与学习


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仅代表是否为第一个包.

至此大体流程走完,初学,后续会细读代码。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值