简体   繁体   English

Live555 RTSP 服务器不使用UDP

[英]Live555 RTSP server does not use UDP

I have a pretty basic live555 RTSP server and client to stream a h264 stream written in c++.我有一个非常基本的 live555 RTSP 服务器和客户端来流式传输用 C++ 编写的 h264 流。

Here's the code I have for the client (adapted from testProgs/testRTSPClient.cpp, bundled with live555)这是我为客户端编写的代码(改编自 testProgs/testRTSPClient.cpp,与 live555 捆绑在一起)

client->scheduler                   = BasicTaskScheduler::createNew();
  client->env                         = BasicUsageEnvironment::createNew(*client->scheduler);
  client->rtspClient                  = NULL;
  RTSP_CLIENT::eventLoopWatchVariable = 0;

  openURL(client, *client->env, string(string("rtsp://") + ip_address + ":" + to_string(BASE_RTSP_PORT + iris_id) + "/iris").c_str());

  client->env->taskScheduler().doEventLoop(&RTSP_CLIENT::eventLoopWatchVariable);

void openURL(RTSP_CLIENT* client, UsageEnvironment& env, char const* rtspURL) {
  // Begin by creating a "RTSPClient" object.  Note that there is a separate "RTSPClient" object for each stream that we wish
  // to receive (even if more than stream uses the same "rtsp://" URL).
  while (!client->rtspClient) {
    client->rtspClient = ourRTSPClient::createNew(env, rtspURL, RTSP_CLIENT_VERBOSITY_LEVEL, "main");
  }

  // Next, send a RTSP "DESCRIBE" command, to get a SDP description for the stream.
  // Note that this command - like all RTSP commands - is sent asynchronously; we do not block, waiting for a response.
  // Instead, the following function call returns immediately, and we handle the RTSP response later, from within the event loop:
  client->rtspClient->sendDescribeCommand(continueAfterDESCRIBE);
}

void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString) {
  do {
    UsageEnvironment& env = rtspClient->envir(); // alias
    StreamClientState& scs = ((ourRTSPClient*)rtspClient)->scs; // alias

    if (resultCode != 0) {
      env << *rtspClient << "Failed to get a SDP description: " << resultString << "\n";
      delete[] resultString;
      break;
    }

    char* const sdpDescription = resultString;
    env << *rtspClient << "Got a SDP description:\n" << sdpDescription << "\n";

    // Create a media session object from this SDP description:
    scs.session = MediaSession::createNew(env, sdpDescription);
    delete[] sdpDescription; // because we don't need it anymore
    if (scs.session == NULL) {
      env << *rtspClient << "Failed to create a MediaSession object from the SDP description: " << env.getResultMsg() << "\n";
      break;
    } else if (!scs.session->hasSubsessions()) {
      env << *rtspClient << "This session has no media subsessions (i.e., no \"m=\" lines)\n";
      break;
    }

    // Then, create and set up our data source objects for the session.  We do this by iterating over the session's 'subsessions',
    // calling "MediaSubsession::initiate()", and then sending a RTSP "SETUP" command, on each one.
    // (Each 'subsession' will have its own data source.)
    scs.iter = new MediaSubsessionIterator(*scs.session);
    setupNextSubsession(rtspClient);
    return;
  } while (0);

  // An unrecoverable error occurred with this stream.
  shutdownStream(rtspClient);
}

Here's the code I have for the server (adapted from testProgs/testOnDemandRTSPServer.cpp, bundled with live555)这是我的服务器代码(改编自 testProgs/testOnDemandRTSPServer.cpp,与 live555 捆绑在一起)

rtsp_server->taskSchedular          = BasicTaskScheduler::createNew();
  rtsp_server->usageEnvironment       = BasicUsageEnvironment::createNew(*rtsp_server->taskSchedular);
  rtsp_server->rtspServer             = RTSPServer::createNew(*rtsp_server->usageEnvironment, BASE_RTSP_PORT + iris_id, NULL);
  rtsp_server->eventLoopWatchVariable = 0;

  if(rtsp_server->rtspServer == NULL) {
    *rtsp_server->usageEnvironment << "Failed to create rtsp server ::" << rtsp_server->usageEnvironment->getResultMsg() <<"\n";
    return false;
  }
  rtsp_server->sms            = ServerMediaSession::createNew(*rtsp_server->usageEnvironment, "iris", "iris", "stream");
  rtsp_server->liveSubSession = H264LiveServerMediaSession::createNew(*rtsp_server->usageEnvironment, true);

  rtsp_server->sms->addSubsession(rtsp_server->liveSubSession);
  rtsp_server->rtspServer->addServerMediaSession(rtsp_server->sms);

rtsp_server->taskSchedular->doEventLoop(&rtsp_server->eventLoopWatchVariable);

I was under the assumption that live555 by default used UDP to transport data to the client from the server, which is what I wanted for it's latency benefits over TCP.我假设 live555 默认使用 UDP 将数据从服务器传输到客户端,这是我想要的,因为它比 TCP 具有延迟优势。 However while running the server client I happened to check netstat and I found this:但是,在运行服务器客户端时,我碰巧检查了 netstat 并发现了这一点:

~# netstat | grep 8554
tcp        0      0 x.x.x.x:8554    wsip-x-x-x-x:39224 ESTABLISHED

It is however showing that the communications are going through TCP not UDP.然而,它表明通信是通过 TCP 而不是 UDP。 I am a bit confused here, am I mis-interpreting netstat here?我在这里有点困惑,我在这里误解了 netstat 吗?

Is there anything I need to tune in my c++ code to force the communication to go through UDP not TCP?有什么我需要在我的 C++ 代码中调整以强制通信通过 UDP 而不是 TCP 的吗?

Okay so I figured out the answer.好的,所以我想出了答案。 To help anyone else who is curious about this, the code is actually all correct.为了帮助对此感到好奇的其他人,代码实际上都是正确的。 There is also no mis-interpretation of netstat.也没有对 netstat 的误解。 RTSP does indeed run over TCP not UDP. RTSP 确实通过 TCP 而不是 UDP 运行。 However the transport method of the A/V data runs on RTP, a connection that RTSP simply negotiates and instantiates.然而,A/V 数据的传输方法在 RTP 上运行,RTSP 只是简单地协商和实例化的连接。 RTP almost always will run over UDP. RTP 几乎总是在 UDP 上运行。 To figure out what port and protocol the A/V data stream is going over you will need to sniff the packets sent out via RTSP.要确定 A/V 数据流通过的端口和协议,您需要嗅探通过 RTSP 发出的数据包。 In my case the A/V data stream was indeed still going over UDP.在我的情况下,A/V 数据流确实仍在通过 UDP。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM