Ejemplo n.º 1
0
	qosMeasurementRecord(struct timeval const& startTime, RTPSource* src)
		: fSource(src), fNext(NULL),
		kbits_per_second_min(1e20), kbits_per_second_max(0),
		kBytesTotal(0.0),
		packet_loss_fraction_min(1.0), packet_loss_fraction_max(0.0),
		totNumPacketsReceived(0), totNumPacketsExpected(0) {
			measurementEndTime = measurementStartTime = startTime;

#ifdef SUPPORT_REAL_RTSP
			if (session->isRealNetworksRDT) { // hack for RealMedia sessions (RDT, not RTP)
				RealRDTSource* rdt = (RealRDTSource*)src;
				kBytesTotal = rdt->totNumKBytesReceived();
				totNumPacketsReceived = rdt->totNumPacketsReceived();
				totNumPacketsExpected = totNumPacketsReceived; // because we use TCP
				return;
			}
#endif
			RTPReceptionStatsDB::Iterator statsIter(src->receptionStatsDB());
			// Assume that there's only one SSRC source (usually the case):
			RTPReceptionStats* stats = statsIter.next(True);
			if (stats != NULL) {
				kBytesTotal = stats->totNumKBytesReceived();
				totNumPacketsReceived = stats->totNumPacketsReceived();
				totNumPacketsExpected = stats->totNumPacketsExpected();
			}
	}
Ejemplo n.º 2
0
void qosMeasurementRecord
::periodicQOSMeasurement(struct timeval const& timeNow) {
  unsigned secsDiff = timeNow.tv_sec - measurementEndTime.tv_sec;
  int usecsDiff = timeNow.tv_usec - measurementEndTime.tv_usec;
  double timeDiff = secsDiff + usecsDiff/1000000.0;
  measurementEndTime = timeNow;

#ifdef SUPPORT_REAL_RTSP
  if (session->isRealNetworksRDT) { // hack for RealMedia sessions (RDT, not RTP)
    RealRDTSource* rdt = (RealRDTSource*)fSource;
    double kBytesTotalNow = rdt->totNumKBytesReceived();
    double kBytesDeltaNow = kBytesTotalNow - kBytesTotal;
    kBytesTotal = kBytesTotalNow;

    double kbpsNow = timeDiff == 0.0 ? 0.0 : 8*kBytesDeltaNow/timeDiff;
    if (kbpsNow < 0.0) kbpsNow = 0.0; // in case of roundoff error
    if (kbpsNow < kbits_per_second_min) kbits_per_second_min = kbpsNow;
    if (kbpsNow > kbits_per_second_max) kbits_per_second_max = kbpsNow;

    totNumPacketsReceived = rdt->totNumPacketsReceived();
    totNumPacketsExpected = totNumPacketsReceived; // because we use TCP
    packet_loss_fraction_min = packet_loss_fraction_max = 0.0; // ditto
    return;
  }
#endif
  RTPReceptionStatsDB::Iterator statsIter(fSource->receptionStatsDB());
  // Assume that there's only one SSRC source (usually the case):
  RTPReceptionStats* stats = statsIter.next(True);
  if (stats != NULL) {
    double kBytesTotalNow = stats->totNumKBytesReceived();
    double kBytesDeltaNow = kBytesTotalNow - kBytesTotal;
    kBytesTotal = kBytesTotalNow;

    double kbpsNow = timeDiff == 0.0 ? 0.0 : 8*kBytesDeltaNow/timeDiff;
    if (kbpsNow < 0.0) kbpsNow = 0.0; // in case of roundoff error
    if (kbpsNow < kbits_per_second_min) kbits_per_second_min = kbpsNow;
    if (kbpsNow > kbits_per_second_max) kbits_per_second_max = kbpsNow;

    unsigned totReceivedNow = stats->totNumPacketsReceived();
    unsigned totExpectedNow = stats->totNumPacketsExpected();
    unsigned deltaReceivedNow = totReceivedNow - totNumPacketsReceived;
    unsigned deltaExpectedNow = totExpectedNow - totNumPacketsExpected;
    totNumPacketsReceived = totReceivedNow;
    totNumPacketsExpected = totExpectedNow;

    double lossFractionNow = deltaExpectedNow == 0 ?
                              0.0 :
                              1.0 - deltaReceivedNow/(double)deltaExpectedNow;
    //if (lossFractionNow < 0.0) lossFractionNow = 0.0; //reordering can cause
    if (lossFractionNow < packet_loss_fraction_min) {
      packet_loss_fraction_min = lossFractionNow;
    }
    if (lossFractionNow > packet_loss_fraction_max) {
      packet_loss_fraction_max = lossFractionNow;
    }
  }
}
Ejemplo n.º 3
0
  qosMeasurementRecord(struct timeval const& startTime, RTPSource* src)
    : fSource(src), fNext(NULL),
      kbits_per_second_min(1e20), kbits_per_second_max(0),
      kBytesTotal(0.0),
      packet_loss_fraction_min(1.0), packet_loss_fraction_max(0.0),
      totNumPacketsReceived(0), totNumPacketsExpected(0) {
    measurementEndTime = measurementStartTime = startTime;

    RTPReceptionStatsDB::Iterator statsIter(src->receptionStatsDB());
    // Assume that there's only one SSRC source (usually the case):
    RTPReceptionStats* stats = statsIter.next(True);
    if (stats != NULL) {
      kBytesTotal = stats->totNumKBytesReceived();
      totNumPacketsReceived = stats->totNumPacketsReceived();
      totNumPacketsExpected = stats->totNumPacketsExpected();
    }
  }
Ejemplo n.º 4
0
void LiveDeviceSource::processReceiverReports()
{
  VLOG(15) << "LiveDeviceSource::processReceiverReports()";
  if (m_pRateAdaptation && m_pSink)
  {
    RTPTransmissionStatsDB::Iterator statsIter(m_pSink->transmissionStatsDB());
    RTPTransmissionStats* stats = statsIter.next();
    if (stats != NULL)
    {
      if (m_uiLastPacketNumReceived == stats->lastPacketNumReceived())
      {
        VLOG(15) << "LiveDeviceSource::processReceiverReports(): no new info";
        // no new info
        return;
      }
      m_uiLastPacketNumReceived = stats->lastPacketNumReceived();
      // convert RtpTransmissionStats to our format
      RtpTransmissionStats rtpStats;
      rtpStats.LastPacketNumReceived = stats->lastPacketNumReceived();
      rtpStats.FirstPacketNumReported = stats->firstPacketNumReported();
      rtpStats.TotalPacketsLost = stats->totNumPacketsLost();
      rtpStats.Jitter = stats->jitter();
      rtpStats.LastSrTime = stats->lastSRTime();
      rtpStats.DiffSrRr = stats->diffSR_RRTime();
      rtpStats.Rtt = stats->roundTripDelay();

      VLOG(2) << "Updating receiver stats: Last packet num received: " << m_uiLastPacketNumReceived;
      lme::SwitchDirection eRateAdvice = m_pRateAdaptation->getRateAdaptAdvice(rtpStats);

      // get hold of rate control interface
      // If we switch for a single source - single client, this will be ok.
      // In the case of multiple clients being connected, this will screw up the rate control as there is currently
      // only one encoder in the media pipeline.
      if (m_pRateControl)
      {
        m_pRateControl->controlBitrate(eRateAdvice);
      }
    }
    else
    {
      VLOG(15) << "LiveDeviceSource::processReceiverReports(): stats null";
    }
  }
}
Ejemplo n.º 5
0
static void
qos_report(void *clientData) {
	int i;
	struct timeval now;
	long long elapsed;
	//
	gettimeofday(&now, NULL);
	elapsed = tvdiff_us(&now, &qos_tv);
	for(i = 0; i < n_qrec; i++) {
		RTPReceptionStatsDB::Iterator statsIter(qrec[i].rtpsrc->receptionStatsDB());
		// Assume that there's only one SSRC source (usually the case):
		RTPReceptionStats* stats = statsIter.next(True);
		unsigned pkts_expected, dExp;
		unsigned pkts_received, dRcvd;
		double KB_received, dKB;
		//
		if(stats == NULL)
			continue;
		pkts_expected = stats->totNumPacketsExpected();
		pkts_received = stats->totNumPacketsReceived();
		KB_received = stats->totNumKBytesReceived();
		// delta ...
		dExp = pkts_expected - qrec[i].pkts_expected;
		dRcvd = pkts_received - qrec[i].pkts_received;
		dKB = KB_received - qrec[i].KB_received;
		// show info
		ga_error("%s-report: %.0fKB rcvd; pkt-loss=%d/%d,%.2f%%; bitrate=%.0fKbps; jitter=%u (freq=%uHz)\n",
			//now.tv_sec, now.tv_usec,
			qrec[i].prefix, dKB, dExp-dRcvd, dExp, 100.0*(dExp-dRcvd)/dExp,
			8000000.0*dKB/elapsed,
			stats->jitter(),
			qrec[i].rtpsrc->timestampFrequency());
		//
		qrec[i].pkts_expected = pkts_expected;
		qrec[i].pkts_received = pkts_received;
		qrec[i].KB_received = KB_received;
	}
	// schedule next qos
	qos_tv = now;
	qos_schedule();
	return;
}
Ejemplo n.º 6
0
void qosMeasurementRecord
::periodicQOSMeasurement(struct timeval const& timeNow) {
  unsigned secsDiff = timeNow.tv_sec - measurementEndTime.tv_sec;
  int usecsDiff = timeNow.tv_usec - measurementEndTime.tv_usec;
  double timeDiff = secsDiff + usecsDiff/1000000.0;
  measurementEndTime = timeNow;

  RTPReceptionStatsDB::Iterator statsIter(fSource->receptionStatsDB());
  // Assume that there's only one SSRC source (usually the case):
  RTPReceptionStats* stats = statsIter.next(True);
  if (stats != NULL) {
    double kBytesTotalNow = stats->totNumKBytesReceived();
    double kBytesDeltaNow = kBytesTotalNow - kBytesTotal;
    kBytesTotal = kBytesTotalNow;

    double kbpsNow = timeDiff == 0.0 ? 0.0 : 8*kBytesDeltaNow/timeDiff;
    if (kbpsNow < 0.0) kbpsNow = 0.0; // in case of roundoff error
    if (kbpsNow < kbits_per_second_min) kbits_per_second_min = kbpsNow;
    if (kbpsNow > kbits_per_second_max) kbits_per_second_max = kbpsNow;

    unsigned totReceivedNow = stats->totNumPacketsReceived();
    unsigned totExpectedNow = stats->totNumPacketsExpected();
    unsigned deltaReceivedNow = totReceivedNow - totNumPacketsReceived;
    unsigned deltaExpectedNow = totExpectedNow - totNumPacketsExpected;
    totNumPacketsReceived = totReceivedNow;
    totNumPacketsExpected = totExpectedNow;

    double lossFractionNow = deltaExpectedNow == 0 ? 0.0
      : 1.0 - deltaReceivedNow/(double)deltaExpectedNow;
    //if (lossFractionNow < 0.0) lossFractionNow = 0.0; //reordering can cause
    if (lossFractionNow < packet_loss_fraction_min) {
      packet_loss_fraction_min = lossFractionNow;
    }
    if (lossFractionNow > packet_loss_fraction_max) {
      packet_loss_fraction_max = lossFractionNow;
    }
  }
}
Ejemplo n.º 7
0
void printQOSData(int exitCode) {
  *env << "begin_QOS_statistics\n";
  
  // Print out stats for each active subsession:
  qosMeasurementRecord* curQOSRecord = qosRecordHead;
  if (session != NULL) {
    MediaSubsessionIterator iter(*session);
    MediaSubsession* subsession;
    while ((subsession = iter.next()) != NULL) {
      RTPSource* src = subsession->rtpSource();
      if (src == NULL) continue;
      
      *env << "subsession\t" << subsession->mediumName()
	   << "/" << subsession->codecName() << "\n";
      
      unsigned numPacketsReceived = 0, numPacketsExpected = 0;
      
      if (curQOSRecord != NULL) {
	numPacketsReceived = curQOSRecord->totNumPacketsReceived;
	numPacketsExpected = curQOSRecord->totNumPacketsExpected;
      }
      *env << "num_packets_received\t" << numPacketsReceived << "\n";
      *env << "num_packets_lost\t" << int(numPacketsExpected - numPacketsReceived) << "\n";
      
      if (curQOSRecord != NULL) {
	unsigned secsDiff = curQOSRecord->measurementEndTime.tv_sec
	  - curQOSRecord->measurementStartTime.tv_sec;
	int usecsDiff = curQOSRecord->measurementEndTime.tv_usec
	  - curQOSRecord->measurementStartTime.tv_usec;
	double measurementTime = secsDiff + usecsDiff/1000000.0;
	*env << "elapsed_measurement_time\t" << measurementTime << "\n";
	
	*env << "kBytes_received_total\t" << curQOSRecord->kBytesTotal << "\n";
	
	*env << "measurement_sampling_interval_ms\t" << qosMeasurementIntervalMS << "\n";
	
	if (curQOSRecord->kbits_per_second_max == 0) {
	  // special case: we didn't receive any data:
	  *env <<
	    "kbits_per_second_min\tunavailable\n"
	    "kbits_per_second_ave\tunavailable\n"
	    "kbits_per_second_max\tunavailable\n";
	} else {
	  *env << "kbits_per_second_min\t" << curQOSRecord->kbits_per_second_min << "\n";
	  *env << "kbits_per_second_ave\t"
	       << (measurementTime == 0.0 ? 0.0 : 8*curQOSRecord->kBytesTotal/measurementTime) << "\n";
	  *env << "kbits_per_second_max\t" << curQOSRecord->kbits_per_second_max << "\n";
	}
	
	*env << "packet_loss_percentage_min\t" << 100*curQOSRecord->packet_loss_fraction_min << "\n";
	double packetLossFraction = numPacketsExpected == 0 ? 1.0
	  : 1.0 - numPacketsReceived/(double)numPacketsExpected;
	if (packetLossFraction < 0.0) packetLossFraction = 0.0;
	*env << "packet_loss_percentage_ave\t" << 100*packetLossFraction << "\n";
	*env << "packet_loss_percentage_max\t"
	     << (packetLossFraction == 1.0 ? 100.0 : 100*curQOSRecord->packet_loss_fraction_max) << "\n";
	
	RTPReceptionStatsDB::Iterator statsIter(src->receptionStatsDB());
	// Assume that there's only one SSRC source (usually the case):
	RTPReceptionStats* stats = statsIter.next(True);
	if (stats != NULL) {
	  *env << "inter_packet_gap_ms_min\t" << stats->minInterPacketGapUS()/1000.0 << "\n";
	  struct timeval totalGaps = stats->totalInterPacketGaps();
	  double totalGapsMS = totalGaps.tv_sec*1000.0 + totalGaps.tv_usec/1000.0;
	  unsigned totNumPacketsReceived = stats->totNumPacketsReceived();
	  *env << "inter_packet_gap_ms_ave\t"
	       << (totNumPacketsReceived == 0 ? 0.0 : totalGapsMS/totNumPacketsReceived) << "\n";
	  *env << "inter_packet_gap_ms_max\t" << stats->maxInterPacketGapUS()/1000.0 << "\n";
	}
	
	curQOSRecord = curQOSRecord->fNext;
      }
    }
  }

  *env << "end_QOS_statistics\n";
  delete qosRecordHead;
}