Added SDP output
This commit is contained in:
		
							parent
							
								
									f0674b9efb
								
							
						
					
					
						commit
						dd2382e858
					
				
					 9 changed files with 383 additions and 84 deletions
				
			
		| 
						 | 
				
			
			@ -172,41 +172,14 @@ namespace Mist{
 | 
			
		|||
    if (reqUrl.size() && lastAnnounce + 5 < Util::bootSecs()){
 | 
			
		||||
      INFO_MSG("Sending announce");
 | 
			
		||||
      lastAnnounce = Util::bootSecs();
 | 
			
		||||
      std::stringstream transportString;
 | 
			
		||||
      transportString.precision(3);
 | 
			
		||||
      transportString << std::fixed
 | 
			
		||||
                      << "v=0\r\n"
 | 
			
		||||
                         "o=- "
 | 
			
		||||
                      << Util::getMS()
 | 
			
		||||
                      << " 1 IN IP4 127.0.0.1\r\n"
 | 
			
		||||
                         "s="
 | 
			
		||||
                      << streamName
 | 
			
		||||
                      << "\r\n"
 | 
			
		||||
                         "c=IN IP4 0.0.0.0\r\n"
 | 
			
		||||
                         "i="
 | 
			
		||||
                      << streamName
 | 
			
		||||
                      << "\r\n"
 | 
			
		||||
                         "u="
 | 
			
		||||
                      << reqUrl
 | 
			
		||||
                      << "\r\n"
 | 
			
		||||
                         "t=0 0\r\n"
 | 
			
		||||
                         "a=tool:" APPIDENT "\r\n"
 | 
			
		||||
                         "a=type:broadcast\r\n"
 | 
			
		||||
                         "a=control:*\r\n"
 | 
			
		||||
                      << "a=range:npt=" << ((double)startTime()) / 1000.0 << "-"
 | 
			
		||||
                      << ((double)endTime()) / 1000.0 << "\r\n";
 | 
			
		||||
 | 
			
		||||
      std::set<size_t> validTracks = M.getValidTracks();
 | 
			
		||||
      for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); ++it){
 | 
			
		||||
        transportString << SDP::mediaDescription(&M, *it);
 | 
			
		||||
      }
 | 
			
		||||
      std::string transportString = generateSDP(reqUrl);
 | 
			
		||||
      HTTP_S.Clean();
 | 
			
		||||
      HTTP_S.SetHeader("Content-Type", "application/sdp");
 | 
			
		||||
      HTTP_S.SetHeader("Content-Base", reqUrl);
 | 
			
		||||
      HTTP_S.method = "ANNOUNCE";
 | 
			
		||||
      HTTP_S.url = reqUrl;
 | 
			
		||||
      HTTP_S.protocol = "RTSP/1.0";
 | 
			
		||||
      HTTP_S.SendRequest(myConn, transportString.str());
 | 
			
		||||
      HTTP_S.SendRequest(myConn, transportString);
 | 
			
		||||
      HTTP_R.Clean();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -320,38 +293,11 @@ namespace Mist{
 | 
			
		|||
        reqUrl = HTTP::URL(HTTP_R.url).link(streamName).getProxyUrl();
 | 
			
		||||
        initialize();
 | 
			
		||||
        userSelect.clear();
 | 
			
		||||
        std::stringstream transportString;
 | 
			
		||||
        transportString.precision(3);
 | 
			
		||||
        transportString << std::fixed
 | 
			
		||||
                        << "v=0\r\n"
 | 
			
		||||
                           "o=- "
 | 
			
		||||
                        << Util::getMS()
 | 
			
		||||
                        << " 1 IN IP4 127.0.0.1\r\n"
 | 
			
		||||
                           "s="
 | 
			
		||||
                        << streamName
 | 
			
		||||
                        << "\r\n"
 | 
			
		||||
                           "c=IN IP4 0.0.0.0\r\n"
 | 
			
		||||
                           "i="
 | 
			
		||||
                        << streamName
 | 
			
		||||
                        << "\r\n"
 | 
			
		||||
                           "u="
 | 
			
		||||
                        << reqUrl
 | 
			
		||||
                        << "\r\n"
 | 
			
		||||
                           "t=0 0\r\n"
 | 
			
		||||
                           "a=tool:" APPIDENT "\r\n"
 | 
			
		||||
                           "a=type:broadcast\r\n"
 | 
			
		||||
                           "a=control:*\r\n"
 | 
			
		||||
                        << "a=range:npt=" << ((double)startTime()) / 1000.0 << "-"
 | 
			
		||||
                        << ((double)endTime()) / 1000.0 << "\r\n";
 | 
			
		||||
 | 
			
		||||
        std::set<size_t> validTracks = Util::wouldSelect(M, targetParams, capa, UA);
 | 
			
		||||
        for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); ++it){
 | 
			
		||||
          transportString << SDP::mediaDescription(&M, *it);
 | 
			
		||||
        }
 | 
			
		||||
        HIGH_MSG("Reply: %s", transportString.str().c_str());
 | 
			
		||||
        std::string transportString = generateSDP(reqUrl);
 | 
			
		||||
        HIGH_MSG("Reply: %s", transportString.c_str());
 | 
			
		||||
        HTTP_S.SetHeader("Content-Base", reqUrl);
 | 
			
		||||
        HTTP_S.SetHeader("Content-Type", "application/sdp");
 | 
			
		||||
        HTTP_S.SetBody(transportString.str());
 | 
			
		||||
        HTTP_S.SetBody(transportString);
 | 
			
		||||
        HTTP_S.SendResponse("200", "OK", myConn);
 | 
			
		||||
        HTTP_R.Clean();
 | 
			
		||||
        continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -479,6 +425,35 @@ namespace Mist{
 | 
			
		|||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// \param reqUrl: URI to additional session information
 | 
			
		||||
  std::string OutRTSP::generateSDP(std::string reqUrl){
 | 
			
		||||
    std::stringstream transportString;
 | 
			
		||||
    transportString.precision(3);
 | 
			
		||||
    // Add session description & time description
 | 
			
		||||
    transportString << std::fixed <<
 | 
			
		||||
      "v=0\r\n"
 | 
			
		||||
      "o=- " << Util::getMS() << " 1 IN IP4 127.0.0.1\r\n"
 | 
			
		||||
      "s=" << streamName << "\r\n"
 | 
			
		||||
      "c=IN IP4 0.0.0.0\r\n"
 | 
			
		||||
      "i=" << streamName << "\r\n"
 | 
			
		||||
      "u=" << reqUrl << "\r\n"
 | 
			
		||||
      "t=0 0\r\n"
 | 
			
		||||
      "a=tool:" APPIDENT "\r\n"
 | 
			
		||||
      "a=type:broadcast\r\n"
 | 
			
		||||
      "a=control:*\r\n";
 | 
			
		||||
     if (M.getLive()){
 | 
			
		||||
       transportString << "a=range:npt=" << ((double)startTime()) / 1000.0 << "-\r\n";
 | 
			
		||||
     }else{
 | 
			
		||||
       transportString << "a=range:npt=" << ((double)startTime()) / 1000.0 << "-" << ((double)endTime()) / 1000.0 << "\r\n";
 | 
			
		||||
     }
 | 
			
		||||
    // Add Media description
 | 
			
		||||
    std::set<size_t> validTracks = M.getValidTracks();
 | 
			
		||||
    for (std::set<size_t>::iterator it = validTracks.begin(); it != validTracks.end(); ++it){
 | 
			
		||||
      transportString << SDP::mediaDescription(&M, *it);
 | 
			
		||||
    }
 | 
			
		||||
    return transportString.str();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Attempts to parse TCP RTP packets at the beginning of the header.
 | 
			
		||||
  /// Returns whether it is safe to attempt to read HTTP/RTSP packets (true) or not (false).
 | 
			
		||||
  bool OutRTSP::handleTCP(){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ namespace Mist{
 | 
			
		|||
    int64_t packetOffset;
 | 
			
		||||
    bool expectTCP;
 | 
			
		||||
    bool checkPort;
 | 
			
		||||
    std::string generateSDP(std::string reqUrl);
 | 
			
		||||
    bool handleTCP();
 | 
			
		||||
    void handleUDP();
 | 
			
		||||
  };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										236
									
								
								src/output/output_sdp.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								src/output/output_sdp.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,236 @@
 | 
			
		|||
#include "output_sdp.h"
 | 
			
		||||
#include "lib/defines.h"
 | 
			
		||||
#include "mist/defines.h"
 | 
			
		||||
#include "src/output/output.h"
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
 | 
			
		||||
namespace Mist{
 | 
			
		||||
  Socket::Connection *mainConn = 0;
 | 
			
		||||
 | 
			
		||||
  OutSDP::OutSDP(Socket::Connection &conn) : HTTPOutput(conn){
 | 
			
		||||
    mainConn = &conn;
 | 
			
		||||
    exitOnNoRTCP = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Function used to send RTP packets over UDP
 | 
			
		||||
  ///\param socket A UDP Connection pointer, sent as a void*, to keep portability.
 | 
			
		||||
  ///\param data The RTP Packet that needs to be sent
 | 
			
		||||
  ///\param len The size of data
 | 
			
		||||
  ///\param channel Not used here, but is kept for compatibility with sendTCP
 | 
			
		||||
  void sendUDP(void *socket, const char *data, size_t len, uint8_t){
 | 
			
		||||
    ((Socket::UDPConnection *)socket)->SendNow(data, len);
 | 
			
		||||
    if (mainConn){mainConn->addUp(len);}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// \brief Initializes the SDP state
 | 
			
		||||
  /// \param  port: Each track will have a data and RTCP port.
 | 
			
		||||
  ///                    These are consecutive and start at startPort
 | 
			
		||||
  /// \param  targetIP: (Multicast supported) IP address we are pushing the stream towards
 | 
			
		||||
  void OutSDP::initTracks(uint32_t & port, std::string targetIP){
 | 
			
		||||
    for (std::map<size_t, Comms::Users>::iterator it = userSelect.begin(); it != userSelect.end(); ++it){
 | 
			
		||||
      SDP::Track newTrk;
 | 
			
		||||
      newTrk.setPackCodec(&M, it->first);
 | 
			
		||||
      if (!newTrk.prepareSockets(targetIP, port)){
 | 
			
		||||
        FAIL_MSG("Could not bind required UDP sockets. Aborting push...");
 | 
			
		||||
        parseData = false;
 | 
			
		||||
        wantRequest = true;
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      // If a starting port was set, increment by 2 for the next track
 | 
			
		||||
      if (port){
 | 
			
		||||
        port+=2;
 | 
			
		||||
      }
 | 
			
		||||
      sdpState.tracks.insert(std::pair<size_t,SDP::Track>(it->first, newTrk));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  void OutSDP::sendHeader(){
 | 
			
		||||
    if (isRecording()){
 | 
			
		||||
      std::string targetIP;
 | 
			
		||||
      if (targetParams["targetIP"].size()){
 | 
			
		||||
        targetIP = targetParams["targetIP"];
 | 
			
		||||
      } else {
 | 
			
		||||
        targetIP = "234.234.234.234";
 | 
			
		||||
      }
 | 
			
		||||
      // If not set, default to random ports we can bind
 | 
			
		||||
      uint32_t port = 0;
 | 
			
		||||
      if (targetParams["startPort"].size()){
 | 
			
		||||
        port = atoll(targetParams["startPort"].c_str());
 | 
			
		||||
      }
 | 
			
		||||
      // Add meta tracks to sdpState
 | 
			
		||||
      initTracks(port, targetIP);
 | 
			
		||||
      myConn.SendNow(generateSDP(targetIP, streamName));
 | 
			
		||||
      INFO_MSG("Pushing %zu tracks towards target address '%s'.", sdpState.tracks.size(), targetIP.c_str());
 | 
			
		||||
    }
 | 
			
		||||
    sentHeader = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// \brief Generates an SDP file which clients can use to connect to the stream
 | 
			
		||||
  ///        initTracks should be called before this function is called, to make sure we have the right ports
 | 
			
		||||
  /// \param targetAddress: the (multicast supported) target, where we will push the stream towards
 | 
			
		||||
  /// \param streamName: the name of the stream we are serving
 | 
			
		||||
  std::string OutSDP::generateSDP(std::string targetAddress, std::string streamName){
 | 
			
		||||
    prevRTCP = Util::bootSecs();
 | 
			
		||||
    std::stringstream sdpAsString;
 | 
			
		||||
    sdpAsString.precision(3);
 | 
			
		||||
    // Add session description & time description
 | 
			
		||||
    sdpAsString << std::fixed <<
 | 
			
		||||
      "v=0\r\n"
 | 
			
		||||
      "o=- " << Util::getMS() << " 1 IN IP4 " << targetAddress << "\r\n"
 | 
			
		||||
      "s=" << streamName << "\r\n"
 | 
			
		||||
      "i=" << streamName << "\r\n"
 | 
			
		||||
      "c=IN IP4 " << targetAddress << "\r\n"
 | 
			
		||||
      "t=0 0\r\n"
 | 
			
		||||
      "a=tool:" APPIDENT "\r\n"
 | 
			
		||||
      "a=recvonly\r\n"
 | 
			
		||||
      "a=type:broadcast\r\n";
 | 
			
		||||
    // Add Media description
 | 
			
		||||
    for (std::map<size_t, Comms::Users>::iterator it = userSelect.begin(); it != userSelect.end(); ++it){
 | 
			
		||||
      DONTEVEN_MSG("Track '%zu' should be pushing data towards UDP port '%" PRIu32 "'", it->first, sdpState.tracks[it->first].portA);
 | 
			
		||||
      sdpAsString << SDP::mediaDescription(&M, it->first, sdpState.tracks.at(it->first).portA);
 | 
			
		||||
    }
 | 
			
		||||
    return sdpAsString.str();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void OutSDP::init(Util::Config *cfg){
 | 
			
		||||
    HTTPOutput::init(cfg);
 | 
			
		||||
    capa["name"] = "SDP";
 | 
			
		||||
    capa["friendly"] = "RTP streams using SDP";
 | 
			
		||||
    capa["desc"] = "Make streams available as a RTP stream, using the SDP";
 | 
			
		||||
    capa["url_rel"] = "/$.sdp";
 | 
			
		||||
    capa["url_match"] = "/$.sdp";
 | 
			
		||||
    capa["codecs"][0u][0u].append("+H264");
 | 
			
		||||
    capa["codecs"][0u][1u].append("+HEVC");
 | 
			
		||||
    capa["codecs"][0u][2u].append("+MPEG2");
 | 
			
		||||
    capa["codecs"][0u][3u].append("+VP8");
 | 
			
		||||
    capa["codecs"][0u][4u].append("+VP9");
 | 
			
		||||
    capa["codecs"][0u][5u].append("+AAC");
 | 
			
		||||
    capa["codecs"][0u][6u].append("+MP3");
 | 
			
		||||
    capa["codecs"][0u][7u].append("+AC3");
 | 
			
		||||
    capa["codecs"][0u][8u].append("+ALAW");
 | 
			
		||||
    capa["codecs"][0u][9u].append("+ULAW");
 | 
			
		||||
    capa["codecs"][0u][10u].append("+PCM");
 | 
			
		||||
    capa["codecs"][0u][11u].append("+opus");
 | 
			
		||||
    capa["codecs"][0u][12u].append("+MP2");
 | 
			
		||||
 | 
			
		||||
    capa["methods"][0u]["handler"] = "http";
 | 
			
		||||
    capa["methods"][0u]["type"] = "html5/application/sdp";
 | 
			
		||||
    capa["methods"][0u]["url_rel"] = "/$.sdp";
 | 
			
		||||
    capa["methods"][0u]["priority"] = 11;
 | 
			
		||||
 | 
			
		||||
    capa["push_urls"].append("/*.sdp");
 | 
			
		||||
 | 
			
		||||
    JSON::Value opt;
 | 
			
		||||
    opt["arg"] = "string";
 | 
			
		||||
    opt["default"] = "";
 | 
			
		||||
    opt["arg_num"] = 1;
 | 
			
		||||
    opt["help"] = "Target filename to store SDP file as, or - for stdout.";
 | 
			
		||||
    cfg->addOption("target", opt);
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  OutSDP::~OutSDP(){
 | 
			
		||||
    // Remove written SDP file, if it was set as the output target
 | 
			
		||||
    if (isRecording()){
 | 
			
		||||
      HTTP::URL target(config->getString("target"));
 | 
			
		||||
      if(target.getExt() == "sdp"){
 | 
			
		||||
        INFO_MSG("Removing .SDP file located at '%s'", target.getFilePath().c_str());
 | 
			
		||||
        std::remove(target.getFilePath().c_str());
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void OutSDP::sendNext(){
 | 
			
		||||
    char *dataPointer = 0;
 | 
			
		||||
    size_t dataLen = 0;
 | 
			
		||||
    thisPacket.getString("data", dataPointer, dataLen);
 | 
			
		||||
    uint64_t timestamp = thisPacket.getTime();
 | 
			
		||||
 | 
			
		||||
    void *socket = 0;
 | 
			
		||||
    void (*callBack)(void *, const char *, size_t, uint8_t) = 0;
 | 
			
		||||
 | 
			
		||||
    // Get data socket and send RTCP
 | 
			
		||||
    if (sdpState.tracks[thisIdx].channel == -1){
 | 
			
		||||
      socket = &sdpState.tracks[thisIdx].data;
 | 
			
		||||
      callBack = sendUDP;
 | 
			
		||||
      if (Util::bootSecs() != sdpState.tracks[thisIdx].rtcpSent){
 | 
			
		||||
        sdpState.tracks[thisIdx].pack.setTimestamp(timestamp * SDP::getMultiplier(&M, thisIdx));
 | 
			
		||||
        sdpState.tracks[thisIdx].rtcpSent = Util::bootSecs();
 | 
			
		||||
        sdpState.tracks[thisIdx].pack.sendRTCP_SR(&sdpState.tracks[thisIdx].rtcp, sendUDP);
 | 
			
		||||
      }
 | 
			
		||||
    }else{
 | 
			
		||||
      FAIL_MSG("RTP SDP output does not support TCP. No data will be sent to the target address");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    uint64_t offset = thisPacket.getInt("offset");
 | 
			
		||||
    sdpState.tracks[thisIdx].pack.setTimestamp((timestamp + offset) * SDP::getMultiplier(&M, thisIdx));
 | 
			
		||||
    sdpState.tracks[thisIdx].pack.sendData(socket, callBack, dataPointer, dataLen,
 | 
			
		||||
                                           sdpState.tracks[thisIdx].channel, meta.getCodec(thisIdx));
 | 
			
		||||
    
 | 
			
		||||
    // Update last RTCP received variable
 | 
			
		||||
    if (exitOnNoRTCP){
 | 
			
		||||
      checkForRTCP(thisIdx);
 | 
			
		||||
      // Exit if no RTCP packets received for 30 seconds
 | 
			
		||||
      if (Util::bootSecs() - prevRTCP > 30){
 | 
			
		||||
        parseData = false;
 | 
			
		||||
        wantRequest = true;
 | 
			
		||||
        WARN_MSG("Shutting down because we have not received RTCP receiver reports for 30 seconds.");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Reads RTCP packets sent back by viewers
 | 
			
		||||
  void OutSDP::checkForRTCP(uint64_t thisIdx){
 | 
			
		||||
    Socket::UDPConnection &socket = sdpState.tracks[thisIdx].rtcp;
 | 
			
		||||
    while (socket.Receive()){
 | 
			
		||||
      prevRTCP = Util::bootSecs();
 | 
			
		||||
      INFO_MSG("received RTCP packet '%u'", prevRTCP);
 | 
			
		||||
      if (myConn){
 | 
			
		||||
        myConn.addDown(sdpState.tracks[thisIdx].rtcp.data.size());
 | 
			
		||||
      };
 | 
			
		||||
      RTP::Packet pack(sdpState.tracks[thisIdx].rtcp.data, sdpState.tracks[thisIdx].rtcp.data.size());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void OutSDP::onHTTP(){
 | 
			
		||||
    std::string targetIP;
 | 
			
		||||
    uint32_t port;
 | 
			
		||||
 | 
			
		||||
    // Init latest RTCP packet time on current time
 | 
			
		||||
    prevRTCP = Util::bootSecs();
 | 
			
		||||
    if (myConn.getHost().size()){
 | 
			
		||||
      targetIP = myConn.getHost();
 | 
			
		||||
    } else {
 | 
			
		||||
      targetIP = "234.234.234.234";
 | 
			
		||||
    }
 | 
			
		||||
    // If not set, default to random ports we can bind
 | 
			
		||||
    if (targetParams["startPort"].size()){
 | 
			
		||||
      port = atoll(targetParams["startPort"].c_str());
 | 
			
		||||
    } else {
 | 
			
		||||
      port = 0;
 | 
			
		||||
    }
 | 
			
		||||
    // When we start an RTP stream via a HTTP request, close it when we no longer receive RTCP packets
 | 
			
		||||
    exitOnNoRTCP = true;
 | 
			
		||||
 | 
			
		||||
    // Add meta tracks to sdpState
 | 
			
		||||
    initTracks(port, targetIP);  
 | 
			
		||||
    INFO_MSG("Pushing %zu tracks towards target address '%s')", sdpState.tracks.size(), targetIP.c_str());
 | 
			
		||||
 | 
			
		||||
    // Send SDP file back
 | 
			
		||||
    H.setCORSHeaders();
 | 
			
		||||
    H.SetBody(generateSDP(targetIP, streamName));
 | 
			
		||||
    H.SendResponse("200", "OK", myConn);
 | 
			
		||||
    H.CleanPreserveHeaders();
 | 
			
		||||
    // No more requests needed. Keep alive until we are no longer receiving RTCP packets
 | 
			
		||||
    parseData = true;
 | 
			
		||||
    wantRequest = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /// Disconnects the user
 | 
			
		||||
  bool OutSDP::onFinish(){
 | 
			
		||||
    INFO_MSG("Shutting down...");
 | 
			
		||||
    if (myConn){myConn.close();}
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}// namespace Mist
 | 
			
		||||
							
								
								
									
										34
									
								
								src/output/output_sdp.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/output/output_sdp.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
#include "output_http.h"
 | 
			
		||||
#include <mist/h264.h>
 | 
			
		||||
#include <mist/http_parser.h>
 | 
			
		||||
#include <mist/rtp.h>
 | 
			
		||||
#include <mist/sdp.h>
 | 
			
		||||
#include <mist/socket.h>
 | 
			
		||||
#include <mist/url.h>
 | 
			
		||||
 | 
			
		||||
namespace Mist{
 | 
			
		||||
  class OutSDP : public HTTPOutput{
 | 
			
		||||
  public:
 | 
			
		||||
    OutSDP(Socket::Connection &conn);
 | 
			
		||||
    ~OutSDP();
 | 
			
		||||
    static void init(Util::Config *cfg);
 | 
			
		||||
    void onHTTP();
 | 
			
		||||
    void sendNext();
 | 
			
		||||
    void sendHeader();
 | 
			
		||||
    bool onFinish();
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    void initTracks(uint32_t & port, std::string targetIP);
 | 
			
		||||
    void checkForRTCP(uint64_t thisIdx);
 | 
			
		||||
    std::string generateSDP(std::string targetAddress, std::string streamName);
 | 
			
		||||
    SDP::State sdpState;
 | 
			
		||||
    uint32_t prevRTCP;
 | 
			
		||||
    bool exitOnNoRTCP;
 | 
			
		||||
    bool isFileTarget(){
 | 
			
		||||
      INFO_MSG("Checking file target! %s", isRecording()?"yes":"no");
 | 
			
		||||
      return isRecording();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
}// namespace Mist
 | 
			
		||||
 | 
			
		||||
typedef Mist::OutSDP mistOut;
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue