
org.jitsi.impl.neomedia.stats.SendTrackStatsImpl Maven / Gradle / Ivy
/*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.impl.neomedia.stats;
import org.jitsi.service.neomedia.stats.*;
import org.jitsi.util.*;
import org.jitsi.utils.stats.*;
/**
* Media stream statistics implementation per send SSRC.
*
* @author Damian Minkov
* @author Boris Grozev
*/
public class SendTrackStatsImpl
extends AbstractTrackStats
implements SendTrackStats
{
/**
* The highest sent sequence number.
*/
private int highestSeq = -1;
/**
* Rate of packet that we did not send (i.e. were lost on their way to us)
*/
RateStatistics packetsNotSentRate = new RateStatistics(1000, 1000F);
/**
* The fraction lost reported in the most recently received RTCP Receiver
* Report.
*/
private double fractionLost = -1d;
/**
* The time at which {@link #fractionLost} was last updated.
*/
private long fractionLostLastUpdate = -1;
/**
* Initializes a new instance.
* @param interval the interval in milliseconds over which average bit- and
* packet-rates will be computed.
*/
SendTrackStatsImpl(int interval, long ssrc)
{
super(interval, ssrc);
}
/**
* Notifies this instance that an RTP packet with a particular sequence
* number was sent (or is about to be sent).
* @param seq the RTP sequence number.
* @param length the length in bytes.
*/
void rtpPacketSent(int seq, int length)
{
long now = System.currentTimeMillis();
// update the bit- and packet-rate
super.packetProcessed(length, now, true);
if (highestSeq == -1)
{
highestSeq = seq;
return;
}
// We monitor the sequence numbers of sent packets in order to
// calculate the actual number of lost packets.
// If we are forwarding the stream (as opposed to generating it
// locally), as is the case in jitsi-videobridge, packets may be lost
// between the sender and us, and we need to take this into account
// when calculating packet loss to the receiver.
int diff = RTPUtils.getSequenceNumberDelta(seq, highestSeq);
if (diff <= 0)
{
// An old packet, already counted as not send. Un-not-send it ;)
packetsNotSentRate.update(-1, now);
}
else
{
// A newer packet.
highestSeq = seq;
// diff = 1 is the "normal" case (i.e. we received the very next
// packet).
if (diff > 1)
{
packetsNotSentRate.update(diff - 1, now);
}
}
// update bytes, packets, loss...
}
/**
* {@inheritDoc}
*
* Returns an estimation of the loss rate based on the most recent RTCP
* Receiver Report that we received, and the rate of "non-sent" packets
* (i.e. in the case of jitsi-videobridge the loss rate from the sender to
* the bridge).
*/
@Override
public double getLossRate()
{
long now = System.currentTimeMillis();
if (fractionLostLastUpdate == -1 || now - fractionLostLastUpdate > 8000)
{
// We haven't received a RR recently, so assume no loss.
return 0;
}
// Take into account packets that we did not send
long packetsNotSent = packetsNotSentRate.getAccumulatedCount(now);
long packetsSent = packetRate.getAccumulatedCount(now);
double fractionNotSent
= (packetsSent+packetsNotSent > 0)
? (packetsNotSent / (packetsNotSent+packetsSent))
: 0;
return Math.max(0, fractionLost - fractionNotSent);
}
/**
* {@inheritDoc}
*/
@Override
public int getHighestSent()
{
return highestSeq;
}
/**
* Notifies this instance that an RTCP packet with a given length in bytes
* was sent (or is about to be sent).
* @param length
*/
void rtcpPacketSent(int length)
{
super.packetProcessed(length, System.currentTimeMillis(), false);
}
/**
* Notifies this instance that an RTCP Receiver Report with a given value
* for the "fraction lost" field was received.
* @param fractionLost the value of the "fraction lost" field from an RTCP
* Receiver Report as an unsigned integer.
*/
void rtcpReceiverReportReceived(int fractionLost)
{
this.fractionLost = fractionLost / 256d;
this.fractionLostLastUpdate = System.currentTimeMillis();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy