live555 RTSPServer源码分析

GenericMediaServer

先分析下 RTSPServer 的父类 GenericMediaServerGenericMediaServer的功能主要分为三部分。

  • 监听服务端端口,收到客户端连接请求时,创建ClientConnection实例和客户端交互。
    static int setUpOurSocket(UsageEnvironment& env, Port& ourPort);
	void incomingConnectionHandlerOnSocket(int serverSocket);

其中ClientConnection 定义handleRequestBytes抽象方法,用于和客户端交互。

	virtual void handleRequestBytes(int newBytesRead) = 0;
  • 维护多媒体会话,每一路多媒体会话包含一路或多路音视频流。
	 void addServerMediaSession(ServerMediaSession* serverMediaSession);
     void removeServerMediaSession(ServerMediaSession* serverMediaSession);

ServerMediaSession 维护一路或多路音视频流,包含所有的SDP信息。

	 char* generateSDPDescription();
	 Boolean addSubsession(ServerMediaSubsession* subsession);
  • 维护ClientSession,用于保活。
    static void noteClientLiveness(ClientSession* clientSession);
    static void livenessTimeoutTask(ClientSession* clientSession);

RTSPServer

RTSP OVER HTTP这里不做分析,RTSPServer的RTSPClientConnection继承父类的ClientConnection实现了handleRequestBytes方法,对客户端请求的数据进行解读,提取RTSP命令,然后调用相应的方法,自身处理以下两条命令,其余交由RTSPClientSession处理。

 virtual void handleCmd_OPTIONS();
 virtual void handleCmd_DESCRIBE(char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr);

RTSPClientConnection处理完OPTIONS, DESCRIBE命令后,收到SETUP命令时,便创建RTSPClientSession对象,由RTSPClientSession对象处理SETUP,PLAY,PAUSE,TEARDOWN等与音视频连接传输有关的命令。

 virtual void handleCmd_SETUP(RTSPClientConnection* ourClientConnection,
               char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr);
 virtual void handleCmd_withinSession(RTSPClientConnection* ourClientConnection,
                                       char const* cmdName,
                                       char const* urlPreSuffix, char const* urlSuffix,
                                       char const* fullRequestStr);
 virtual void handleCmd_TEARDOWN(RTSPClientConnection* ourClientConnection,
                  ServerMediaSubsession* subsession);
 virtual void handleCmd_PLAY(RTSPClientConnection* ourClientConnection,
                              ServerMediaSubsession* subsession, char const* fullRequestStr);
 virtual void handleCmd_PAUSE(RTSPClientConnection* ourClientConnection,
                                  ServerMediaSubsession* subsession);

接下来分析几个重要的方法:

handleCmd_DESCRIBE

返回请求的ServerMediaSession的音视频能力,使用SDP协议描述。先找到对应的ServerMediaSession,然后在ServerMediaSession中遍历ServerMediaSubsession

ServerMediaSession::generateSDPDescription()
	->ServerMediaSubsession::sdpLines()=0

handleCmd_SETUP

如果使用RAW_UDP协议,使用serverRTPPort端口创建 BasicUDPSink对象。

否则,分别使用serverRTPPortserverRTCPPort创建socket,然后使用rtpsock创建RTPSink对象。

handleCmd_PLAY

主要方法:startStream

对于RTP_UDPRTP_TCP协议,则创建RTCPInstance对象,并启动运行。

    if (fRTCPInstance == NULL && fRTPSink != NULL)
    {
        // Create (and start) a 'RTCP instance' for this RTP sink:
        fRTCPInstance = fMaster.createRTCP(fRTCPgs, fTotalBW, (unsigned char*)fMaster.fCNAME, fRTPSink);
        // Note: This starts RTCP running automatically
        fRTCPInstance->setAppHandler(fMaster.fAppHandlerTask, fMaster.fAppHandlerClientData);
    }

对于RAW_UDP协议,使用handleCmd_SETUP中创建的BasicUDPSink

 fUDPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);

fUDPSinkfMediaSource中循环读取音视频帧,然后通过handleCmd_SETUP中创建的socket发送:

fGS->output(envir(), fOutputBuffer, frameSize);

对于RTP_UDPRTP_TCP协议,使用handleCmd_SETUP中创建的RTPSink

fRTPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);

RTPSinkfMediaSource中循环读取音视频帧,在发送时,RTP_UDP使用handleCmd_SETUP中创建的socket发送:

    // Normal case: Send as a UDP packet:
    if (!fGS->output(envir(), packet, packetSize)) success = False;

RTP_TCP则使用ClientConnection 的tcpsocket发送,并且在发送数据帧之前,先发送4字节帧头,指明通道号和数据包大小。

  	u_int8_t framingHeader[4];
    framingHeader[0] = '$';
    framingHeader[1] = streamChannelId;
    framingHeader[2] = (u_int8_t) ((packetSize&0xFF00)>>8);
    framingHeader[3] = (u_int8_t) (packetSize&0xFF);
    if (!sendDataOverTCP(socketNum, framingHeader, 4, False)) break;

    if (!sendDataOverTCP(socketNum, packet, packetSize, True)) break;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值