WebRTC fixes/improvements:
- Added public host setting - Implemented Sender Report based track time syncing - Added 10 second timeout for output connections (no timeout for input connections) - Timing fixes
This commit is contained in:
		
							parent
							
								
									cff43da016
								
							
						
					
					
						commit
						19a55828a3
					
				
					 4 changed files with 84 additions and 6 deletions
				
			
		
							
								
								
									
										22
									
								
								lib/rtp.cpp
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								lib/rtp.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -616,6 +616,7 @@ namespace RTP{
 | 
				
			||||||
    if (M.getCodec(tid) == "opus"){
 | 
					    if (M.getCodec(tid) == "opus"){
 | 
				
			||||||
      m = 48.0;
 | 
					      m = 48.0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    bootMsOffset = M.getBootMsOffset();
 | 
				
			||||||
    setProperties(M.getID(tid), M.getCodec(tid), M.getType(tid), M.getInit(tid), m);
 | 
					    setProperties(M.getID(tid), M.getCodec(tid), M.getType(tid), M.getInit(tid), m);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -625,6 +626,24 @@ namespace RTP{
 | 
				
			||||||
    cbInit = cbI;
 | 
					    cbInit = cbI;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Improves A/V sync by providing an NTP time source
 | 
				
			||||||
 | 
					  /// msDiff is the amount of millis our current NTP time is ahead of the sync moment NTP time
 | 
				
			||||||
 | 
					  /// May be negative, if we're behind instead of ahead.
 | 
				
			||||||
 | 
					  void toDTSC::timeSync(uint32_t rtpTime, int64_t msDiff){
 | 
				
			||||||
 | 
					    if (!firstTime){return;}
 | 
				
			||||||
 | 
					    uint64_t rtp64Time = rtpTime;
 | 
				
			||||||
 | 
					    if (recentWrap){
 | 
				
			||||||
 | 
					      if (rtpTime > 0x80000000lu){rtp64Time -= 0x100000000ll;}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    uint64_t msTime = (rtp64Time - firstTime + 1 + 0x100000000ull * wrapArounds) / multiplier + milliSync;
 | 
				
			||||||
 | 
					    int32_t rtpDiff = (bootMsOffset + msTime) - (Util::bootMS() - msDiff);
 | 
				
			||||||
 | 
					    if (rtpDiff > 25 || rtpDiff < -25){
 | 
				
			||||||
 | 
					      INFO_MSG("RTP difference (%s %s): %" PRId32 "ms, syncing...", type.c_str(), codec.c_str(), rtpDiff);
 | 
				
			||||||
 | 
					      milliSync -= rtpDiff;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Adds an RTP packet to the converter, outputting DTSC packets and/or updating init data,
 | 
					  /// Adds an RTP packet to the converter, outputting DTSC packets and/or updating init data,
 | 
				
			||||||
  /// as-needed.
 | 
					  /// as-needed.
 | 
				
			||||||
  void toDTSC::addRTP(const RTP::Packet &pkt){
 | 
					  void toDTSC::addRTP(const RTP::Packet &pkt){
 | 
				
			||||||
| 
						 | 
					@ -636,6 +655,7 @@ namespace RTP{
 | 
				
			||||||
    // This part isn't codec-specific, so we do it before anything else.
 | 
					    // This part isn't codec-specific, so we do it before anything else.
 | 
				
			||||||
    int64_t pTime = pkt.getTimeStamp();
 | 
					    int64_t pTime = pkt.getTimeStamp();
 | 
				
			||||||
    if (!firstTime){
 | 
					    if (!firstTime){
 | 
				
			||||||
 | 
					      milliSync = Util::bootMS() - bootMsOffset;
 | 
				
			||||||
      firstTime = pTime + 1;
 | 
					      firstTime = pTime + 1;
 | 
				
			||||||
      INFO_MSG("RTP timestamp rollover expected in " PRETTY_PRINT_TIME,
 | 
					      INFO_MSG("RTP timestamp rollover expected in " PRETTY_PRINT_TIME,
 | 
				
			||||||
               PRETTY_ARG_TIME((0xFFFFFFFFul - firstTime) / multiplier / 1000));
 | 
					               PRETTY_ARG_TIME((0xFFFFFFFFul - firstTime) / multiplier / 1000));
 | 
				
			||||||
| 
						 | 
					@ -651,7 +671,7 @@ namespace RTP{
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    prevTime = pkt.getTimeStamp();
 | 
					    prevTime = pkt.getTimeStamp();
 | 
				
			||||||
    uint64_t msTime = ((uint64_t)pTime - firstTime + 1 + 0x100000000ull * wrapArounds) / multiplier;
 | 
					    uint64_t msTime = ((uint64_t)pTime - firstTime + 1 + 0x100000000ull * wrapArounds) / multiplier + milliSync;
 | 
				
			||||||
    char *pl = (char *)pkt.getPayload();
 | 
					    char *pl = (char *)pkt.getPayload();
 | 
				
			||||||
    uint32_t plSize = pkt.getPayloadSize();
 | 
					    uint32_t plSize = pkt.getPayloadSize();
 | 
				
			||||||
    bool missed = lastSeq != (pkt.getSequence() - 1);
 | 
					    bool missed = lastSeq != (pkt.getSequence() - 1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,6 +139,7 @@ namespace RTP{
 | 
				
			||||||
    void setCallbacks(void (*cbPack)(const DTSC::Packet &pkt),
 | 
					    void setCallbacks(void (*cbPack)(const DTSC::Packet &pkt),
 | 
				
			||||||
                      void (*cbInit)(const uint64_t track, const std::string &initData));
 | 
					                      void (*cbInit)(const uint64_t track, const std::string &initData));
 | 
				
			||||||
    void addRTP(const RTP::Packet &rPkt);
 | 
					    void addRTP(const RTP::Packet &rPkt);
 | 
				
			||||||
 | 
					    void timeSync(uint32_t rtpTime, int64_t msDiff);
 | 
				
			||||||
    virtual void outPacket(const DTSC::Packet &pkt){
 | 
					    virtual void outPacket(const DTSC::Packet &pkt){
 | 
				
			||||||
      if (cbPack){cbPack(pkt);}
 | 
					      if (cbPack){cbPack(pkt);}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -148,6 +149,7 @@ namespace RTP{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public:
 | 
					  public:
 | 
				
			||||||
    uint64_t trackId;
 | 
					    uint64_t trackId;
 | 
				
			||||||
 | 
					    uint64_t bootMsOffset;
 | 
				
			||||||
    double multiplier;    ///< Multiplier to convert from millis to RTP time
 | 
					    double multiplier;    ///< Multiplier to convert from millis to RTP time
 | 
				
			||||||
    std::string codec;    ///< Codec of this track
 | 
					    std::string codec;    ///< Codec of this track
 | 
				
			||||||
    std::string type;     ///< Type of this track
 | 
					    std::string type;     ///< Type of this track
 | 
				
			||||||
| 
						 | 
					@ -159,6 +161,7 @@ namespace RTP{
 | 
				
			||||||
    bool recentWrap;      ///< True if a wraparound happened recently.
 | 
					    bool recentWrap;      ///< True if a wraparound happened recently.
 | 
				
			||||||
    uint32_t prevTime;
 | 
					    uint32_t prevTime;
 | 
				
			||||||
    uint64_t firstTime;
 | 
					    uint64_t firstTime;
 | 
				
			||||||
 | 
					    int32_t milliSync;
 | 
				
			||||||
    void (*cbPack)(const DTSC::Packet &pkt);
 | 
					    void (*cbPack)(const DTSC::Packet &pkt);
 | 
				
			||||||
    void (*cbInit)(const uint64_t track, const std::string &initData);
 | 
					    void (*cbInit)(const uint64_t track, const std::string &initData);
 | 
				
			||||||
    // Codec-specific handlers
 | 
					    // Codec-specific handlers
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,7 @@ namespace Mist{
 | 
				
			||||||
  /* ------------------------------------------------ */
 | 
					  /* ------------------------------------------------ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  OutWebRTC::OutWebRTC(Socket::Connection &myConn) : HTTPOutput(myConn){
 | 
					  OutWebRTC::OutWebRTC(Socket::Connection &myConn) : HTTPOutput(myConn){
 | 
				
			||||||
 | 
					    lastRecv = Util::bootMS();
 | 
				
			||||||
    stats_jitter = 0;
 | 
					    stats_jitter = 0;
 | 
				
			||||||
    stats_nacknum = 0;
 | 
					    stats_nacknum = 0;
 | 
				
			||||||
    stats_lossnum = 0;
 | 
					    stats_lossnum = 0;
 | 
				
			||||||
| 
						 | 
					@ -76,6 +77,7 @@ namespace Mist{
 | 
				
			||||||
    didReceiveKeyFrame = false;
 | 
					    didReceiveKeyFrame = false;
 | 
				
			||||||
    doDTLS = true;
 | 
					    doDTLS = true;
 | 
				
			||||||
    volkswagenMode = false;
 | 
					    volkswagenMode = false;
 | 
				
			||||||
 | 
					    syncedNTPClock = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (cert.init("NL", "webrtc", "webrtc") != 0){
 | 
					    if (cert.init("NL", "webrtc", "webrtc") != 0){
 | 
				
			||||||
      onFail("Failed to create the certificate.", true);
 | 
					      onFail("Failed to create the certificate.", true);
 | 
				
			||||||
| 
						 | 
					@ -147,7 +149,7 @@ namespace Mist{
 | 
				
			||||||
    capa["optional"]["preferredaudiocodec"]["option"] = "--webrtc-audio-codecs";
 | 
					    capa["optional"]["preferredaudiocodec"]["option"] = "--webrtc-audio-codecs";
 | 
				
			||||||
    capa["optional"]["preferredaudiocodec"]["short"] = "A";
 | 
					    capa["optional"]["preferredaudiocodec"]["short"] = "A";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    capa["optional"]["bindhost"]["name"] = "UDP bind address";
 | 
					    capa["optional"]["bindhost"]["name"] = "UDP bind address (internal)";
 | 
				
			||||||
    capa["optional"]["bindhost"]["help"] = "Interface address or hostname to bind SRTP UDP socket "
 | 
					    capa["optional"]["bindhost"]["help"] = "Interface address or hostname to bind SRTP UDP socket "
 | 
				
			||||||
                                           "to. Defaults to originating interface address.";
 | 
					                                           "to. Defaults to originating interface address.";
 | 
				
			||||||
    capa["optional"]["bindhost"]["default"] = "";
 | 
					    capa["optional"]["bindhost"]["default"] = "";
 | 
				
			||||||
| 
						 | 
					@ -155,6 +157,13 @@ namespace Mist{
 | 
				
			||||||
    capa["optional"]["bindhost"]["option"] = "--bindhost";
 | 
					    capa["optional"]["bindhost"]["option"] = "--bindhost";
 | 
				
			||||||
    capa["optional"]["bindhost"]["short"] = "B";
 | 
					    capa["optional"]["bindhost"]["short"] = "B";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    capa["optional"]["pubhost"]["name"] = "UDP bind address (public)";
 | 
				
			||||||
 | 
					    capa["optional"]["pubhost"]["help"] = "Interface address or hostname for clients to connect to. Defaults to internal address.";
 | 
				
			||||||
 | 
					    capa["optional"]["pubhost"]["default"] = "";
 | 
				
			||||||
 | 
					    capa["optional"]["pubhost"]["type"] = "str";
 | 
				
			||||||
 | 
					    capa["optional"]["pubhost"]["option"] = "--pubhost";
 | 
				
			||||||
 | 
					    capa["optional"]["pubhost"]["short"] = "H";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    capa["optional"]["mergesessions"]["name"] = "merge sessions";
 | 
					    capa["optional"]["mergesessions"]["name"] = "merge sessions";
 | 
				
			||||||
    capa["optional"]["mergesessions"]["help"] =
 | 
					    capa["optional"]["mergesessions"]["help"] =
 | 
				
			||||||
        "if enabled, merges together all views from a single user into a single combined session. "
 | 
					        "if enabled, merges together all views from a single user into a single combined session. "
 | 
				
			||||||
| 
						 | 
					@ -230,6 +239,7 @@ namespace Mist{
 | 
				
			||||||
  // The signaling data contains commands that are used to start
 | 
					  // The signaling data contains commands that are used to start
 | 
				
			||||||
  // an input or output stream.
 | 
					  // an input or output stream.
 | 
				
			||||||
  void OutWebRTC::onWebsocketFrame(){
 | 
					  void OutWebRTC::onWebsocketFrame(){
 | 
				
			||||||
 | 
					    lastRecv = Util::bootMS();
 | 
				
			||||||
    if (webSock->frameType != 1){
 | 
					    if (webSock->frameType != 1){
 | 
				
			||||||
      HIGH_MSG("Ignoring non-text websocket frame");
 | 
					      HIGH_MSG("Ignoring non-text websocket frame");
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
| 
						 | 
					@ -730,6 +740,9 @@ namespace Mist{
 | 
				
			||||||
  // This function is called to handle an offer from a peer that wants to push data towards us.
 | 
					  // This function is called to handle an offer from a peer that wants to push data towards us.
 | 
				
			||||||
  bool OutWebRTC::handleSignalingCommandRemoteOfferForInput(SDP::Session &sdpSession){
 | 
					  bool OutWebRTC::handleSignalingCommandRemoteOfferForInput(SDP::Session &sdpSession){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!meta.getBootMsOffset()){meta.setBootMsOffset(Util::bootMS());}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (webRTCInputOutputThread != NULL){
 | 
					    if (webRTCInputOutputThread != NULL){
 | 
				
			||||||
      FAIL_MSG("It seems that we're already have a webrtc i/o thread running.");
 | 
					      FAIL_MSG("It seems that we're already have a webrtc i/o thread running.");
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
| 
						 | 
					@ -884,6 +897,9 @@ namespace Mist{
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Util::Procs::socketList.insert(udp.getSock());
 | 
					    Util::Procs::socketList.insert(udp.getSock());
 | 
				
			||||||
 | 
					    if (config && config->hasOption("pubhost") && config->getString("pubhost").size()){
 | 
				
			||||||
 | 
					      bindAddr = config->getString("pubhost");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    sdpAnswer.setCandidate(bindAddr, udpPort);
 | 
					    sdpAnswer.setCandidate(bindAddr, udpPort);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -978,6 +994,7 @@ namespace Mist{
 | 
				
			||||||
                usernameLocal.c_str());
 | 
					                usernameLocal.c_str());
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    lastRecv = Util::bootMS();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::string remoteIP = "";
 | 
					    std::string remoteIP = "";
 | 
				
			||||||
    uint32_t remotePort = 0;
 | 
					    uint32_t remotePort = 0;
 | 
				
			||||||
| 
						 | 
					@ -1010,6 +1027,7 @@ namespace Mist{
 | 
				
			||||||
      FAIL_MSG("Failed to parse a DTLS packet.");
 | 
					      FAIL_MSG("Failed to parse a DTLS packet.");
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    lastRecv = Util::bootMS();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!dtlsHandshake.hasKeyingMaterial()){
 | 
					    if (!dtlsHandshake.hasKeyingMaterial()){
 | 
				
			||||||
      if (packetLog.is_open()){packetLog << "[" << Util::bootMS() << "]" << "DTLS: No keying material (yet)" << std::endl;}
 | 
					      if (packetLog.is_open()){packetLog << "[" << Util::bootMS() << "]" << "DTLS: No keying material (yet)" << std::endl;}
 | 
				
			||||||
| 
						 | 
					@ -1077,6 +1095,7 @@ namespace Mist{
 | 
				
			||||||
        FAIL_MSG("Failed to unprotect a RTP packet.");
 | 
					        FAIL_MSG("Failed to unprotect a RTP packet.");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      lastRecv = Util::bootMS();
 | 
				
			||||||
      RTP::Packet unprotPack(udp.data, len);
 | 
					      RTP::Packet unprotPack(udp.data, len);
 | 
				
			||||||
      DONTEVEN_MSG("%s", unprotPack.toString().c_str());
 | 
					      DONTEVEN_MSG("%s", unprotPack.toString().c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1108,6 +1127,7 @@ namespace Mist{
 | 
				
			||||||
        FAIL_MSG("Failed to unprotect RTCP.");
 | 
					        FAIL_MSG("Failed to unprotect RTCP.");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      lastRecv = Util::bootMS();
 | 
				
			||||||
      uint8_t fmt = udp.data[0] & 0x1F;
 | 
					      uint8_t fmt = udp.data[0] & 0x1F;
 | 
				
			||||||
      if (pt == 77 || pt == 65){
 | 
					      if (pt == 77 || pt == 65){
 | 
				
			||||||
        //77/65 = nack
 | 
					        //77/65 = nack
 | 
				
			||||||
| 
						 | 
					@ -1154,10 +1174,23 @@ namespace Mist{
 | 
				
			||||||
        for (it = webrtcTracks.begin(); it != webrtcTracks.end(); ++it){
 | 
					        for (it = webrtcTracks.begin(); it != webrtcTracks.end(); ++it){
 | 
				
			||||||
          if (it->second.SSRC == SSRC){
 | 
					          if (it->second.SSRC == SSRC){
 | 
				
			||||||
            it->second.sorter.lastBootMS = Util::bootMS();
 | 
					            it->second.sorter.lastBootMS = Util::bootMS();
 | 
				
			||||||
            it->second.sorter.lastNTP = Bit::btohl(udp.data+10);;
 | 
					            it->second.sorter.lastNTP = Bit::btohl(udp.data+10);
 | 
				
			||||||
 | 
					            uint64_t ntpTime = Bit::btohll(udp.data + 8);
 | 
				
			||||||
 | 
					            uint32_t rtpTime = Bit::btohl(udp.data + 16);
 | 
				
			||||||
            uint32_t packets = Bit::btohl(udp.data + 20);
 | 
					            uint32_t packets = Bit::btohl(udp.data + 20);
 | 
				
			||||||
            uint32_t bytes = Bit::btohl(udp.data + 24);
 | 
					            uint32_t bytes = Bit::btohl(udp.data + 24);
 | 
				
			||||||
            HIGH_MSG("Received sender report for track %s (%" PRIu32 " pkts, %" PRIu32 "b)", it->second.rtpToDTSC.codec.c_str(), packets, bytes);
 | 
					            HIGH_MSG("Received sender report for track %s (%" PRIu32 " pkts, %" PRIu32 "b) time: %" PRIu32 " RTP = %" PRIu64 " NTP", it->second.rtpToDTSC.codec.c_str(), packets, bytes, rtpTime, ntpTime);
 | 
				
			||||||
 | 
					            if (rtpTime && ntpTime){
 | 
				
			||||||
 | 
					              //msDiff is the amount of millis our current NTP time is ahead of the sync moment NTP time
 | 
				
			||||||
 | 
					              //May be negative, if we're behind instead of ahead.
 | 
				
			||||||
 | 
					              uint64_t ntpDiff = Util::getNTP()-ntpTime;
 | 
				
			||||||
 | 
					              int64_t msDiff = (ntpDiff>>32) * 1000 + (ntpDiff & 0xFFFFFFFFul) / 4294967.295;
 | 
				
			||||||
 | 
					              if (!syncedNTPClock){
 | 
				
			||||||
 | 
					                syncedNTPClock = true;
 | 
				
			||||||
 | 
					                ntpClockDifference = -msDiff;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              it->second.rtpToDTSC.timeSync(rtpTime, msDiff+ntpClockDifference);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1338,12 +1371,23 @@ namespace Mist{
 | 
				
			||||||
    if(doDTLS){
 | 
					    if(doDTLS){
 | 
				
			||||||
      while (keepGoing() && !dtlsHandshake.hasKeyingMaterial()){
 | 
					      while (keepGoing() && !dtlsHandshake.hasKeyingMaterial()){
 | 
				
			||||||
        if (!handleWebRTCInputOutput()){Util::sleep(10);}
 | 
					        if (!handleWebRTCInputOutput()){Util::sleep(10);}
 | 
				
			||||||
 | 
					        if (lastRecv < Util::bootMS() - 10000){
 | 
				
			||||||
 | 
					          WARN_MSG("Killing idle connection in handshake phase");
 | 
				
			||||||
 | 
					          onFail("idle connection in handshake phase", false);
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    sentHeader = true;
 | 
					    sentHeader = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void OutWebRTC::sendNext(){
 | 
					  void OutWebRTC::sendNext(){
 | 
				
			||||||
 | 
					    if (lastRecv < Util::bootMS() - 10000){
 | 
				
			||||||
 | 
					      WARN_MSG("Killing idle connection");
 | 
				
			||||||
 | 
					      onFail("idle connection", false);
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Handle nice move-over to new track ID
 | 
					    // Handle nice move-over to new track ID
 | 
				
			||||||
    if (prevVidTrack != INVALID_TRACK_ID && thisIdx != prevVidTrack && M.getType(thisIdx) == "video"){
 | 
					    if (prevVidTrack != INVALID_TRACK_ID && thisIdx != prevVidTrack && M.getType(thisIdx) == "video"){
 | 
				
			||||||
      if (!thisPacket.getFlag("keyframe")){
 | 
					      if (!thisPacket.getFlag("keyframe")){
 | 
				
			||||||
| 
						 | 
					@ -1401,7 +1445,14 @@ namespace Mist{
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    WebRTCTrack &rtcTrack = *trackPointer;
 | 
					    WebRTCTrack &rtcTrack = *trackPointer;
 | 
				
			||||||
    rtcTrack.rtpPacketizer.setTimestamp(thisPacket.getTime() * SDP::getMultiplier(&M, thisIdx));
 | 
					    double mult = SDP::getMultiplier(&M, thisIdx);
 | 
				
			||||||
 | 
					    // This checks if we have a whole integer multiplier, and if so,
 | 
				
			||||||
 | 
					    // ensures only integer math is used to prevent rounding errors
 | 
				
			||||||
 | 
					    if (mult == (uint64_t)mult){
 | 
				
			||||||
 | 
					      rtcTrack.rtpPacketizer.setTimestamp(thisPacket.getTime() * (uint64_t)mult);
 | 
				
			||||||
 | 
					    }else{
 | 
				
			||||||
 | 
					      rtcTrack.rtpPacketizer.setTimestamp(thisPacket.getTime() * mult);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool isKeyFrame = thisPacket.getFlag("keyframe");
 | 
					    bool isKeyFrame = thisPacket.getFlag("keyframe");
 | 
				
			||||||
    didReceiveKeyFrame = isKeyFrame;
 | 
					    didReceiveKeyFrame = isKeyFrame;
 | 
				
			||||||
| 
						 | 
					@ -1427,7 +1478,7 @@ namespace Mist{
 | 
				
			||||||
    rtcTrack.rtpPacketizer.sendData(&udp, onRTPPacketizerHasDataCallback, dataPointer, dataLen,
 | 
					    rtcTrack.rtpPacketizer.sendData(&udp, onRTPPacketizerHasDataCallback, dataPointer, dataLen,
 | 
				
			||||||
                                    rtcTrack.payloadType, M.getCodec(thisIdx));
 | 
					                                    rtcTrack.payloadType, M.getCodec(thisIdx));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!lastSR.count(thisIdx) || lastSR[thisIdx] < Util::bootMS() + 250){
 | 
					    if (!lastSR.count(thisIdx) || lastSR[thisIdx]+500 < Util::bootMS()){
 | 
				
			||||||
      lastSR[thisIdx] = Util::bootMS();
 | 
					      lastSR[thisIdx] = Util::bootMS();
 | 
				
			||||||
      rtcTrack.rtpPacketizer.sendRTCP_SR((void *)&udp, onRTPPacketizerHasRTCPDataCallback);
 | 
					      rtcTrack.rtpPacketizer.sendRTCP_SR((void *)&udp, onRTPPacketizerHasRTCPDataCallback);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,6 +145,7 @@ namespace Mist{
 | 
				
			||||||
    void onRTPPacketizerHasRTCPPacket(const char *data, uint32_t nbytes);
 | 
					    void onRTPPacketizerHasRTCPPacket(const char *data, uint32_t nbytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
 | 
					    uint64_t lastRecv;
 | 
				
			||||||
    uint64_t lastPackMs;
 | 
					    uint64_t lastPackMs;
 | 
				
			||||||
    std::ofstream jitterLog;
 | 
					    std::ofstream jitterLog;
 | 
				
			||||||
    std::ofstream packetLog;
 | 
					    std::ofstream packetLog;
 | 
				
			||||||
| 
						 | 
					@ -234,6 +235,9 @@ namespace Mist{
 | 
				
			||||||
                                                          ///< future.
 | 
					                                                          ///< future.
 | 
				
			||||||
    std::map<uint32_t, nackBuffer> outBuffers;
 | 
					    std::map<uint32_t, nackBuffer> outBuffers;
 | 
				
			||||||
    std::map<size_t, uint64_t> lastSR;
 | 
					    std::map<size_t, uint64_t> lastSR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int64_t ntpClockDifference;
 | 
				
			||||||
 | 
					    bool syncedNTPClock;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}// namespace Mist
 | 
					}// namespace Mist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue