예제 #1
0
int SyntheticInput::deliverFeedback_(std::shared_ptr<DataPacket> fb_packet) {
  RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(fb_packet->data);
  if (chead->isFeedback()) {
    if (chead->getBlockCount() == 0 && (chead->getLength()+1) * 4  == fb_packet->length) {
      return 0;
    }
    char* moving_buf = fb_packet->data;
    int rtcp_length = 0;
    int total_length = 0;
    do {
      moving_buf += rtcp_length;
      chead = reinterpret_cast<RtcpHeader*>(moving_buf);
      rtcp_length = (ntohs(chead->length) + 1) * 4;
      total_length += rtcp_length;
      switch (chead->packettype) {
        case RTCP_RTP_Feedback_PT:
          // NACKs are already handled by WebRtcConnection. RRs won't be handled.
          total_packets_nacked_++;
          break;
        case RTCP_PS_Feedback_PT:
          switch (chead->getBlockCount()) {
            case RTCP_PLI_FMT:
            case RTCP_FIR_FMT:
              sendPLI();
              break;
            case RTCP_AFB:
              char *unique_id = reinterpret_cast<char*>(&chead->report.rembPacket.uniqueid);
              if (!strncmp(unique_id, "REMB", 4)) {
                uint64_t bitrate = chead->getBrMantis() << chead->getBrExp();
                calculateSizeAndPeriod(bitrate, kDefaultAudioBitrate);
              }
              break;
          }
      }
    } while (total_length < fb_packet->length);
  }
  return 0;
}
예제 #2
0
  int RtcpForwarder::analyzeFeedback(char *buf, int len) {
    RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(buf);
    if (chead->isFeedback()) {      
      uint32_t sourceSsrc = chead->getSourceSSRC();
      // We try to add it just in case it is not there yet (otherwise its noop)
      this->addSourceSsrc(sourceSsrc);

      struct timeval now;
      gettimeofday(&now, NULL);
      char* movingBuf = buf;
      int rtcpLength = 0;
      int totalLength = 0;
      int currentBlock = 0;

      do {
        movingBuf+=rtcpLength;
        chead = reinterpret_cast<RtcpHeader*>(movingBuf);
        rtcpLength = (ntohs(chead->length)+1) * 4;
        totalLength += rtcpLength;
        switch(chead->packettype){
          case RTCP_SDES_PT:
            ELOG_DEBUG("SDES");
            break;
          case RTCP_BYE:
            ELOG_DEBUG("BYE");
            break;
          case RTCP_Receiver_PT:
            if (chead->getSourceSSRC() == rtcpSource_->getVideoSourceSSRC()){
              ELOG_DEBUG("Analyzing Video RR: PacketLost %u, Ratio %u, currentBlock %d, blocks %d, sourceSSRC %u, ssrc %u changed to %u", 
                  chead->getLostPackets(), 
                  chead->getFractionLost(), 
                  currentBlock, 
                  chead->getBlockCount(), 
                  chead->getSourceSSRC(), 
                  chead->getSSRC(),
                  rtcpSink_->getVideoSinkSSRC());
              chead->setSSRC(rtcpSink_->getVideoSinkSSRC());
            }else{
              ELOG_DEBUG("Analyzing Audio RR: PacketLost %u, Ratio %u, currentBlock %d, blocks %d, sourceSSRC %u, ssrc %u changed to %u", 
                  chead->getLostPackets(), 
                  chead->getFractionLost(), 
                  currentBlock, 
                  chead->getBlockCount(), 
                  chead->getSourceSSRC(), 
                  chead->getSSRC(),
                  rtcpSink_->getAudioSinkSSRC());
              chead->setSSRC(rtcpSink_->getAudioSinkSSRC());
            }
            break;
          case RTCP_RTP_Feedback_PT:
            ELOG_DEBUG("RTP FB: Usually NACKs: %u, currentBlock %d", chead->getBlockCount(), currentBlock);
            ELOG_DEBUG("NACK PID %u BLP %u", chead->getNackPid(), chead->getNackBlp());
            // We analyze NACK to avoid sending repeated NACKs
            break;
          case RTCP_PS_Feedback_PT:
            //            ELOG_DEBUG("RTCP PS FB TYPE: %u", chead->getBlockCount() );
            switch(chead->getBlockCount()){
              case RTCP_PLI_FMT:
                ELOG_DEBUG("PLI Message, currentBlock %d", currentBlock);
                // 1: PLI, 4: FIR
                break;
              case RTCP_SLI_FMT:
                ELOG_WARN("SLI Message");
                break;
              case RTCP_FIR_FMT:
                ELOG_WARN("FIR Message");
                break;
              case RTCP_AFB:
                {
                  char *uniqueId = (char*)&chead->report.rembPacket.uniqueid;
                  if (!strncmp(uniqueId,"REMB", 4)){
                    uint64_t bitrate = chead->getBrMantis() << chead->getBrExp();
                    uint64_t cappedBitrate = 0;
                    cappedBitrate = bitrate < maxVideoBw_? bitrate: maxVideoBw_;
                    if (bitrate < maxVideoBw_){
                      cappedBitrate = bitrate;
                    }else{
                      cappedBitrate = maxVideoBw_;
                    }
                    ELOG_DEBUG("Received REMB %lu, partnum %u, cappedBitrate %lu", bitrate, currentBlock, cappedBitrate);
                    chead->setREMBBitRate(cappedBitrate);
                  }
                  else{
                    ELOG_WARN("Unsupported AFB Packet not REMB")
                  }
                  break;
                }
              default:
                ELOG_WARN("Unsupported RTCP_PS FB TYPE %u",chead->getBlockCount());
                break;
            }
            break;
          default:
            ELOG_WARN("Unknown RTCP Packet, %d", chead->packettype);
            break;
        }
        currentBlock++;
      } while (totalLength < len);
      return len;
    }
void SenderBandwidthEstimationHandler::read(Context *ctx, std::shared_ptr<dataPacket> packet) {
  RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(packet->data);
  if (chead->isFeedback() && chead->getSourceSSRC() == connection_->getVideoSinkSSRC()) {
    char* packet_pointer = packet->data;
    int rtcp_length = 0;
    int total_length = 0;
    int current_block = 0;

    do {
      packet_pointer+=rtcp_length;
      chead = reinterpret_cast<RtcpHeader*>(packet_pointer);
      rtcp_length = (ntohs(chead->length) + 1) * 4;
      total_length += rtcp_length;
      ELOG_DEBUG("%s ssrc %u, sourceSSRC %u, PacketType %u", connection_->toLog(),
          chead->getSSRC(),
          chead->getSourceSSRC(),
          chead->getPacketType());
      switch (chead->packettype) {
        case RTCP_Receiver_PT:
          {
            ELOG_DEBUG("%s, Analyzing Video RR: PacketLost %u, Ratio %u, current_block %d, blocks %d"
                ", sourceSSRC %u, ssrc %u",
                connection_->toLog(),
                chead->getLostPackets(),
                chead->getFractionLost(),
                current_block,
                chead->getBlockCount(),
                chead->getSourceSSRC(),
                chead->getSSRC());
            // calculate RTT + Update receiver block
            uint32_t delay_since_last_ms = (chead->getDelaySinceLastSr() * 1000) / 65536;
            int64_t now_ms = ClockUtils::timePointToMs(clock::now());
            uint32_t last_sr = chead->getLastSr();

            auto value = std::find_if(sr_delay_data_.begin(), sr_delay_data_.end(),
                [last_sr](const std::shared_ptr<SrDelayData> sr_info) {
                return sr_info->sr_ntp == last_sr;
                });
            if (value != sr_delay_data_.end()) {
                uint32_t delay = now_ms - (*value)->sr_send_time - delay_since_last_ms;
                sender_bwe_->UpdateReceiverBlock(chead->getFractionLost(),
                    delay, period_packets_sent_, now_ms);
                period_packets_sent_ = 0;
                updateEstimate();
            }
          }
          break;
        case RTCP_PS_Feedback_PT:
          {
            if (chead->getBlockCount() == RTCP_AFB) {
              char *uniqueId = reinterpret_cast<char*>(&chead->report.rembPacket.uniqueid);
              if (!strncmp(uniqueId, "REMB", 4)) {
                int64_t now_ms = ClockUtils::timePointToMs(clock::now());
                uint64_t bitrate = chead->getBrMantis() << chead->getBrExp();
                ELOG_DEBUG("%s message: Updating Estimate with REMB, bitrate %llu", connection_->toLog(),
                    bitrate);
                sender_bwe_->UpdateReceiverEstimate(now_ms, bitrate);
                sender_bwe_->UpdateEstimate(now_ms);
                updateEstimate();
              } else {
                ELOG_DEBUG("%s message: Unsupported AFB Packet not REMB", connection_->toLog());
              }
            }
          }
          break;
        default:
          break;
      }
      current_block++;
    } while (total_length < packet->length);
  }
  ctx->fireRead(packet);
}
예제 #4
0
  void RtcpProcessor::analyzeFeedback(char *buf, int len) {

    RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(buf);
    if (chead->isFeedback()) {      
      uint32_t sourceSsrc = chead->getSourceSSRC();
      // We try to add it just in case it is not there yet (otherwise its noop)
      this->addSourceSsrc(sourceSsrc);

      boost::mutex::scoped_lock mlock(mapLock_);
      boost::shared_ptr<RtcpData> theData = rtcpData_[sourceSsrc];
      boost::mutex::scoped_lock lock(theData->dataLock);
      struct timeval now;
      gettimeofday(&now, NULL);
      char* movingBuf = buf;
      int rtcpLength = 0;
      int totalLength = 0;
      int partNum = 0;
      uint32_t calculatedlsr, delay, calculateLastSr;

      do {
        movingBuf+=rtcpLength;
        chead = reinterpret_cast<RtcpHeader*>(movingBuf);
        rtcpLength = (ntohs(chead->length)+1) * 4;
        totalLength += rtcpLength;
        switch(chead->packettype){
          case RTCP_SDES_PT:
            ELOG_DEBUG("SDES");
            break;
          case RTCP_BYE:
            ELOG_DEBUG("BYE");
            break;
          case RTCP_Receiver_PT:
            theData->rrsReceivedInPeriod++;
            if (chead->getSourceSSRC() == rtcpSource_->getVideoSourceSSRC()){
              ELOG_DEBUG("Analyzing Video RR: PacketLost %u, Ratio %u, partNum %d, blocks %d, sourceSSRC %u", chead->getLostPackets(), chead->getFractionLost(), partNum, chead->getBlockCount(), chead->getSourceSSRC());
            }else{
              ELOG_DEBUG("Analyzing Audio RR: PacketLost %u, Ratio %u, partNum %d, blocks %d, sourceSSRC %u", chead->getLostPackets(), chead->getFractionLost(), partNum, chead->getBlockCount(), chead->getSourceSSRC());
            }
            theData->ratioLost = theData->ratioLost > chead->getFractionLost()? theData->ratioLost: chead->getFractionLost();  
            theData->totalPacketsLost = theData->totalPacketsLost > chead->getLostPackets()? theData->totalPacketsLost : chead->getLostPackets();
            theData->highestSeqNumReceived = theData->highestSeqNumReceived > chead->getHighestSeqnum()? theData->highestSeqNumReceived : chead->getHighestSeqnum();
            theData->jitter = theData->jitter > chead->getJitter()? theData->jitter: chead->getJitter();
            calculateLastSr = chead->getLastSr();
            calculatedlsr = (chead->getDelaySinceLastSr()*1000)/65536;
            for (std::list<boost::shared_ptr<SrData>>::iterator it=theData->senderReports.begin(); it != theData->senderReports.end(); ++it){
              if ((*it)->srNtp == calculateLastSr){  
                uint64_t nowms = (now.tv_sec * 1000) + (now.tv_usec / 1000);
                uint64_t sentts = ((*it)->timestamp.tv_sec * 1000) + ((*it)->timestamp.tv_usec / 1000);
                delay = nowms - sentts - calculatedlsr;

              }
            }

            if (theData->lastSr==0||theData->lastDelay < delay){
              ELOG_DEBUG("Recording DLSR %u, lastSR %u last delay %u, calculated delay %u for SSRC %u", chead->getDelaySinceLastSr(), chead->getLastSr(), theData->lastDelay, delay, sourceSsrc);
              theData->lastSr = chead->getLastSr();
              theData->delaySinceLastSr = chead->getDelaySinceLastSr();
              theData->lastSrUpdated = now;
              theData->lastDelay = delay;
            }else{
              //              ELOG_DEBUG("Not recording delay %u, lastDelay %u", delay, theData->lastDelay);
            }
            break;
          case RTCP_RTP_Feedback_PT:
            ELOG_DEBUG("RTP FB: Usually NACKs: %u, partNum %d", chead->getBlockCount(), partNum);
            ELOG_DEBUG("PID %u BLP %u", chead->getNackPid(), chead->getNackBlp());
            theData->shouldSendNACK = true;
            theData->nackSeqnum = chead->getNackPid();
            theData->nackBlp = chead->getNackBlp();
            theData->requestRr = true;
            break;
          case RTCP_PS_Feedback_PT:
            //            ELOG_DEBUG("RTCP PS FB TYPE: %u", chead->getBlockCount() );
            switch(chead->getBlockCount()){
              case RTCP_PLI_FMT:
                ELOG_DEBUG("PLI Message, partNum %d", partNum);
                // 1: PLI, 4: FIR
                theData->shouldSendPli = true;
                break;
              case RTCP_SLI_FMT:
                ELOG_DEBUG("SLI Message");
                break;
              case RTCP_FIR_FMT:
                ELOG_DEBUG("FIR Message");
                break;
              case RTCP_AFB:
                {
                  char *uniqueId = (char*)&chead->report.rembPacket.uniqueid;
                  if (!strncmp(uniqueId,"REMB", 4)){
                    uint64_t bitrate = chead->getBrMantis() << chead->getBrExp();
                    ELOG_DEBUG("Received REMB %lu", bitrate);
                    if ((bitrate<theData->reportedBandwidth) || theData->reportedBandwidth==0){
                      ELOG_DEBUG("Should send Packet REMB, before BR %lu, will send with Br %lu", theData->reportedBandwidth, bitrate);
                      theData->reportedBandwidth = bitrate;  
                      theData->shouldSendREMB = true;
                    }
                  }
                  else{
                    ELOG_DEBUG("Unsupported AFB Packet not REMB")
                  }
                  break;
                }
              default:
                ELOG_WARN("Unsupported RTCP_PS FB TYPE %u",chead->getBlockCount());
                break;
            }
            break;
          default:
            ELOG_DEBUG("Unknown RTCP Packet, %d", chead->packettype);
            break;
        }

        partNum++;
      } while (totalLength < len);
    }
예제 #5
0
int RtcpAggregator::analyzeFeedback(char *buf, int len) {
  RtcpHeader *chead = reinterpret_cast<RtcpHeader*>(buf);
  if (chead->isFeedback()) {
    if (chead->getBlockCount() == 0 && (chead->getLength()+1) * 4  == len) {
      ELOG_DEBUG("Ignoring empty RR");
      return 0;
    }
    uint32_t sourceSsrc = chead->getSourceSSRC();
    // We try to add it just in case it is not there yet (otherwise its noop)
    this->addSourceSsrc(sourceSsrc);

    boost::mutex::scoped_lock mlock(mapLock_);
    boost::shared_ptr<RtcpData> theData = rtcpData_[sourceSsrc];
    boost::mutex::scoped_lock lock(theData->dataLock);
    uint64_t nowms = ClockUtils::timePointToMs(clock::now());
    char* movingBuf = buf;
    int rtcpLength = 0;
    int totalLength = 0;
    int partNum = 0;
    uint16_t currentNackPos = 0;
    uint16_t blp = 0;
    uint32_t lostPacketSeq = 0;
    uint32_t delay = 0;
    uint32_t calculatedlsr, calculateLastSr, extendedSeqNo;

    do {
      movingBuf += rtcpLength;
      chead = reinterpret_cast<RtcpHeader*>(movingBuf);
      rtcpLength = (ntohs(chead->length) + 1) * 4;
      totalLength += rtcpLength;
      switch (chead->packettype) {
        case RTCP_SDES_PT:
          ELOG_DEBUG("SDES");
          break;
        case RTCP_BYE:
          ELOG_DEBUG("BYE");
          break;
        case RTCP_Receiver_PT:
          theData->rrsReceivedInPeriod++;
          if (rtcpSource_->isVideoSourceSSRC(chead->getSourceSSRC())) {
            ELOG_DEBUG("Analyzing Video RR: PacketLost %u, Ratio %u, partNum %d, blocks %d, sourceSSRC %u, ssrc %u",
                        chead->getLostPackets(), chead->getFractionLost(), partNum, chead->getBlockCount(),
                        chead->getSourceSSRC(), chead->getSSRC());
          } else {
            ELOG_DEBUG("Analyzing Audio RR: PacketLost %u, Ratio %u, partNum %d, blocks %d, sourceSSRC %u, ssrc %u",
                        chead->getLostPackets(), chead->getFractionLost(), partNum, chead->getBlockCount(),
                        chead->getSourceSSRC(), chead->getSSRC());
          }
          theData->ratioLost = theData->ratioLost > chead->getFractionLost() ?
                                            theData->ratioLost : chead->getFractionLost();
          theData->totalPacketsLost = theData->totalPacketsLost > chead->getLostPackets() ?
                                            theData->totalPacketsLost : chead->getLostPackets();
          extendedSeqNo = chead->getSeqnumCycles();
          extendedSeqNo = (extendedSeqNo << 16) + chead->getHighestSeqnum();
          if (extendedSeqNo > theData->extendedSeqNo) {
            theData->extendedSeqNo = extendedSeqNo;
            theData->highestSeqNumReceived = chead->getHighestSeqnum();
            theData->seqNumCycles = chead->getSeqnumCycles();
          }
          theData->jitter = theData->jitter > chead->getJitter()? theData->jitter: chead->getJitter();
          calculateLastSr = chead->getLastSr();
          calculatedlsr = (chead->getDelaySinceLastSr() * 1000) / 65536;
          for (std::list<boost::shared_ptr<SrDelayData>>::iterator it = theData->senderReports.begin();
                        it != theData->senderReports.end(); ++it) {
            if ((*it)->sr_ntp == calculateLastSr) {
              uint64_t sentts = (*it)->sr_send_time;
              delay = nowms - sentts - calculatedlsr;
            }
          }

          if (theData->lastSr == 0 || theData->lastDelay < delay) {
            ELOG_DEBUG("Recording DLSR %u, lastSR %u last delay %u, calculated delay %u for SSRC %u",
                        chead->getDelaySinceLastSr(), chead->getLastSr(), theData->lastDelay, delay, sourceSsrc);
            theData->lastSr = chead->getLastSr();
            theData->delaySinceLastSr = chead->getDelaySinceLastSr();
            theData->last_sr_updated = nowms;
            theData->lastDelay = delay;
          } else {
            // ELOG_DEBUG("Not recording delay %u, lastDelay %u", delay, theData->lastDelay);
          }
          break;
        case RTCP_RTP_Feedback_PT:
          {
            ELOG_DEBUG("RTP FB: Usually NACKs: %u, partNum %d", chead->getBlockCount(), partNum);
            ELOG_DEBUG("NACK PID %u BLP %u", chead->getNackPid(), chead->getNackBlp());
            // We analyze NACK to avoid sending repeated NACKs
            blp = chead->getNackBlp();
            theData->shouldSendNACK = false;
            std::pair<std::set<uint32_t>::iterator, bool> ret;
            ret = theData->nackedPackets_.insert(chead->getNackPid());
            if (ret.second) {
              ELOG_DEBUG("We received PID NACK for unacked packet %u", chead->getNackPid());
              theData->shouldSendNACK = true;
            } else {
              if (theData->nackedPackets_.size() >= MAP_NACK_SIZE) {
                while (theData->nackedPackets_.size() >= MAP_NACK_SIZE) {
                  theData->nackedPackets_.erase(theData->nackedPackets_.begin());
                }
              }
              ELOG_DEBUG("We received PID NACK for ALREADY acked packet %u", chead->getNackPid());
            }
            if (blp != 0) {
              for (int i = 0; i < 16; i++) {
                currentNackPos = blp & 0x0001;
                blp = blp >> 1;

                if (currentNackPos == 1) {
                  lostPacketSeq = chead->getNackPid() + 1 + i;
                  ret = theData->nackedPackets_.insert(lostPacketSeq);
                  if (ret.second) {
                    ELOG_DEBUG("We received NACK for unacked packet %u", lostPacketSeq);
                  } else {
                    ELOG_DEBUG("We received NACK for ALREADY acked packet %u", lostPacketSeq);
                  }
                  theData->shouldSendNACK |=ret.second;
                }
              }
            }
            if (theData->shouldSendNACK) {
              ELOG_DEBUG("Will send NACK");
              theData->nackSeqnum = chead->getNackPid();
              theData->nackBlp = chead->getNackBlp();
              theData->requestRr = true;
            } else {
              ELOG_DEBUG("I'm ignoring a NACK");
            }
          }
          break;
        case RTCP_PS_Feedback_PT:
          //            ELOG_DEBUG("RTCP PS FB TYPE: %u", chead->getBlockCount() );
          switch (chead->getBlockCount()) {
            case RTCP_PLI_FMT:
              ELOG_DEBUG("PLI Message, partNum %d", partNum);
              // 1: PLI, 4: FIR
              theData->shouldSendPli = true;
              break;
            case RTCP_SLI_FMT:
              ELOG_DEBUG("SLI Message");
              break;
            case RTCP_FIR_FMT:
              ELOG_DEBUG("FIR Message");
              break;
            case RTCP_AFB:
              {
                char *uniqueId = reinterpret_cast<char*>(&chead->report.rembPacket.uniqueid);
                if (!strncmp(uniqueId, "REMB", 4)) {
                  uint64_t bitrate = chead->getBrMantis() << chead->getBrExp();
                  ELOG_DEBUG("Received REMB %lu", bitrate);
                  if (bitrate < defaultVideoBw_) {
                    theData->reportedBandwidth = bitrate;
                    theData->shouldSendREMB = true;
                  } else {
                    theData->reportedBandwidth = defaultVideoBw_;
                  }
                } else {
                  ELOG_DEBUG("Unsupported AFB Packet not REMB")
                }
                break;
              }
            default:
              ELOG_WARN("Unsupported RTCP_PS FB TYPE %u", chead->getBlockCount());
              break;
          }
          break;
        default:
          ELOG_DEBUG("Unknown RTCP Packet, %d", chead->packettype);
          break;
      }

      partNum++;
    } while (totalLength < len);
  }
  return 0;
}