Darwin Streaming Server中RTSP会话流程解析(Darwin流媒体服务器解析1)
一、首先是本地监听的建立:StartServer() ->
-->QTSServer::Initialize()
--->QTSServer::CreateListeners() //函数中根据本地xml配置文件中的rtsp_port进行监听的建立
-->QTSServer::StartTasks() //开启Socket读取
具体函数在:
QTSServer::CreateListeners() { … newListenerArray[curPortIndex] = NEW RTSPListenerSocket(); QTSS_Error err = newListenerArray[curPortIndex]->Initialize(thePortTrackers[count3].fIPAddr, thePortTrackers[count3].fPort);//fIPAddr为本地IP,fPort为配置端口号 … }
void QTSServer::StartTasks() { fRTCPTask = new RTCPTask(); fStatsTask = new RTPStatsUpdaterTask(); // // Start listening for (UInt32 x = 0; x < fNumListeners; x++) fListeners[x]->RequestEvent(EV_RE); }
二、会话建立
先看RTSPListenerSocket类:
Socket的读取统一归于EventContext类中的EventThread线程,具体到EventThread::Entry()中的select_waitevent()捕获。
EventThread::Entry()函数中查找EventThread::fRefTable,获取对应的EventContext。得到的是EventContext类型的派生类RTSPListenerSocket。
EventThread::Entry() {
… EventContext* theContext = (EventContext*)ref->GetObject(); theContext->ProcessEvent(theCurrentEvent.er_eventbits); …
}
调用RTSPListenerSocket的ProcessEvent()函数,进而调用TCPListenerSocket::ProcessEvent(),在TCPListenerSocket::ProcessEvent()中accept Socket
theTask = this->GetSessionTask(&theSocket);//创建RTSPSession if (theTask == NULL) { //this should be a disconnect. do an ioctl call? close(osSocket); if (theSocket) theSocket->fState &= ~kConnected; // turn off connected state } else { Assert(osSocket != EventContext::kInvalidFileDesc); //set options on the socket //we are a server, always disable nagle algorithm int one = 1; int err = ::setsockopt(osSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int)); AssertV(err == 0, OSThread::GetErrno()); err = ::setsockopt(osSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&one, sizeof(int)); AssertV(err == 0, OSThread::GetErrno()); int sndBufSize = 96L * 1024L; err = ::setsockopt(osSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sndBufSize, sizeof(int)); AssertV(err == 0, OSThread::GetErrno()); //setup the socket. When there is data on the socket, //theTask will get an kReadEvent event theSocket->Set(osSocket, &addr); theSocket->InitNonBlocking(osSocket); theSocket->SetTask(theTask); //将处理Socket的类转入到RTSPSession theSocket->RequestEvent(EV_RE); //将当前Socket加入select侦听队列 }
将(TCPSocket*)theSocket加入到侦听队列中,从上以后就开始对该条已建立accept的(TCPSocket*)theSocket描述请求由此处所创建的(RTSPSession*)theTask进行处理。
三、RTSP交互
同样Socket的读取统一归于EventContext类中的EventThread线程,具体到EventThread::Entry()中的select_waitevent()捕获。
EventThread::Entry()函数中查找EventThread::fRefTable,获取对应的EventContext。此时查找到第二部分中加入到侦听队列的Socket,进入
到EventContext中的ProcessEvent()函数:
virtual void ProcessEvent(int /*eventBits*/) { if (EVENTCONTEXT_DEBUG) { if (fTask== NULL) qtss_printf("EventContext::ProcessEvent context=%lu task=NULL\n",(UInt32) this); else qtss_printf("EventContext::ProcessEvent context=%lu task=%lu TaskName=%s\n",(UInt32)this,(UInt32) fTask, fTask->fTaskName); } if (fTask != NULL) fTask->Signal(Task::kReadEvent); }
激活第二部分中theSocket所映射的theTask,进行Socket读取。此处fTask就是RTSPSession类。把RTSPSession加入到TaskThread的队列等待RTSPSession::Run()被调用,
进而就是RTSPSession::Run()对具体的RTSP请求进行的处理。
好了,今天就简单推进到此处,下一部分将深入到RTSPSession中具体对报文如何解析,以及RTSPSession如何与其他模块&Task进行交互进行分析!
------------------------------------------------------------
本文转自www.easydarwin.org,更多开源流媒体解决方案,请关注我们的微信:EasyDarwin
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术