1

I have a pretty basic live555 RTSP server and client to stream a h264 stream written in c++.

Here's the code I have for the client (adapted from testProgs/testRTSPClient.cpp, bundled with 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)

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. However while running the server client I happened to check netstat and I found this:

~# 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. I am a bit confused here, am I mis-interpreting netstat here?

Is there anything I need to tune in my c++ code to force the communication to go through UDP not TCP?

ktb92677
  • 407
  • 4
  • 16
  • This doesn't seem to be a programming question – SergeyA Feb 19 '19 at 20:38
  • Did you happen to read through the question? I have a c++ program that is not working correctly. I am asking a question about that – ktb92677 Feb 19 '19 at 20:40
  • No, you are not. You are asking how to **use** a particular program (a sample program, it seems) which happens to be written in C++. – SergeyA Feb 19 '19 at 20:43
  • No, that is not at all what I am asking. I have updated my question to reflect this. – ktb92677 Feb 19 '19 at 20:45
  • Still wrong. Code should be provided in the question itself, and it should be MCVE. If you are unsure how to ask questions here, you might want to take a tour on Stack Overflow. – SergeyA Feb 19 '19 at 20:49
  • Okay, I've made yet another update. Is this more permissible? – ktb92677 Feb 19 '19 at 20:58
  • I think the people who left the minus ratings on my questions should reconsider their ratings... is there anyway to get them to reconsider? – ktb92677 Feb 20 '19 at 03:10
  • @ktb92677 The people who downvoted your question are unlikely to reconsider. It is up to the asker to get things right the first time around and with the massive influx of questions that we're getting nowadays, nobody has time to go back and check if. Your answer is quite decent, though, so good on you. – dandan78 Feb 20 '19 at 20:50
  • @dandan78 thank you very much for the kind words :) I will try and get my questions right the first time from now on – ktb92677 Feb 20 '19 at 22:54

1 Answers1

1

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. RTSP does indeed run over TCP not UDP. However the transport method of the A/V data runs on RTP, a connection that RTSP simply negotiates and instantiates. RTP almost always will run over 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. In my case the A/V data stream was indeed still going over UDP.

ktb92677
  • 407
  • 4
  • 16