Skip to content

Commit

Permalink
Merge pull request #154 from jitsi/stats-per-ssrc
Browse files Browse the repository at this point in the history
Adds statistics per ssrc in MediaStreamStats and their implementation.
  • Loading branch information
lyubomir committed May 12, 2016
2 parents acdb141 + 4abbd34 commit a16a3e6
Show file tree
Hide file tree
Showing 7 changed files with 514 additions and 47 deletions.
108 changes: 108 additions & 0 deletions src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java
@@ -0,0 +1,108 @@
/*
* 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;

import org.jitsi.impl.neomedia.transform.rtcp.*;
import org.jitsi.service.neomedia.*;

/**
* Media stream statistics per send or receive SSRC.
*
* @author Damian Minkov
*/
public abstract class AbstractMediaStreamSSRCStats
implements MediaStreamSSRCStats
{
/**
* The <tt>StatisticsEngine</tt> of this instance.
*/
protected final StatisticsEngine statisticsEngine;

/**
* The SSRC of this piece of statistics.
*/
protected final long ssrc;

/**
* The last jitter received/sent in an RTCP feedback (in ms).
*/
private double jitter = 0;

/**
* The RTT computed with the RTCP feedback (cf. RFC3550, section 6.4.1,
* subsection "delay since last SR (DLSR): 32 bits"). {@code -1} if the RTT
* has not been computed yet. Otherwise, the RTT in milliseconds.
*/
private long rttMs = -1;

/**
* Initializes a new {@code AbstractMediaStreamSSRCStats} instance.
*
* @param ssrc the SSRC of the {@code MediaStream} to associate with the new
* instance.
* @param statisticsEngine the {@code StatisticsEngine} instance to use.
*/
AbstractMediaStreamSSRCStats(long ssrc, StatisticsEngine statisticsEngine)
{
this.ssrc = ssrc;
this.statisticsEngine = statisticsEngine;
}

/**
* {@inheritDoc}
*/
public long getSSRC()
{
return ssrc;
}

/**
* {@inheritDoc}
*/
public double getJitter()
{
return jitter;
}

/**
* Sets the last jitter that was sent/received.
*
* @param jitter the new value to set on this instance as the last
* sent/received jitter
*/
public void setJitter(double jitter)
{
this.jitter = jitter;
}

/**
* {@inheritDoc}
*/
public long getRttMs()
{
return rttMs;
}

/**
* Sets a specific value on {@link #rttMs}.
*
* @param rttMs the new value to set on {@link #rttMs}
*/
public void setRttMs(long rttMs)
{
this.rttMs = rttMs;
}
}
48 changes: 48 additions & 0 deletions src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java
@@ -0,0 +1,48 @@
/*
* 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;

import org.jitsi.impl.neomedia.transform.rtcp.*;

/**
* Media stream statistics implementation per received SSRC.
*
* @author Damian Minkov
*/
public class MediaStreamReceivedSSRCStats
extends AbstractMediaStreamSSRCStats
{
MediaStreamReceivedSSRCStats(long ssrc, StatisticsEngine statisticsEngine)
{
super(ssrc, statisticsEngine);
}

/**
* {@inheritDoc}
*/
public long getNbBytes()
{
return statisticsEngine.getNbBytesReceived(ssrc);
}

/**
* {@inheritDoc}
*/
public long getNbPackets()
{
return statisticsEngine.getRtpPacketsReceived(ssrc);
}
}
48 changes: 48 additions & 0 deletions src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java
@@ -0,0 +1,48 @@
/*
* 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;

import org.jitsi.impl.neomedia.transform.rtcp.*;

/**
* Media stream statistics implementation per send SSRC.
*
* @author Damian Minkov
*/
public class MediaStreamSentSSRCStats
extends AbstractMediaStreamSSRCStats
{
MediaStreamSentSSRCStats(long ssrc, StatisticsEngine statisticsEngine)
{
super(ssrc, statisticsEngine);
}

/**
* {@inheritDoc}
*/
public long getNbBytes()
{
return statisticsEngine.getNbBytesSent(ssrc);
}

/**
* {@inheritDoc}
*/
public long getNbPackets()
{
return statisticsEngine.getRtpPacketsSent(ssrc);
}
}
78 changes: 65 additions & 13 deletions src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java
Expand Up @@ -31,7 +31,6 @@

import org.jitsi.impl.neomedia.device.*;
import org.jitsi.impl.neomedia.rtcp.*;
import org.jitsi.impl.neomedia.rtp.*;
import org.jitsi.impl.neomedia.rtp.remotebitrateestimator.*;
import org.jitsi.impl.neomedia.transform.rtcp.*;
import org.jitsi.service.neomedia.*;
Expand Down Expand Up @@ -67,6 +66,12 @@ private enum StreamDirection
private static final Logger logger
= Logger.getLogger(MediaStreamStatsImpl.class);

/**
* List of stats per ssrc.
*/
private final Map<Long,AbstractMediaStreamSSRCStats>[] mediaStreamStats
= new Map[] { new HashMap<>(), new HashMap<>() };

/**
* Computes an Exponentially Weighted Moving Average (EWMA). Thus, the most
* recent history has a more preponderant importance in the average
Expand Down Expand Up @@ -827,24 +832,23 @@ public int getLocalPort()
* @param streamDirection The stream direction (DOWNLOAD or UPLOAD) of the
* stream from which this function retrieve the number of sent/received
* bytes.
*
* @return the number of sent/received bytes for this stream.
*/
private long getNbBytes(StreamDirection streamDirection)
{
StreamRTPManager rtpManager = mediaStreamImpl.queryRTPManager();
StatisticsEngine statisticsEngine
= mediaStreamImpl.getStatisticsEngine();
long nbBytes = 0;

if(rtpManager != null)
if (statisticsEngine != null)
{
switch(streamDirection)
switch (streamDirection)
{
case DOWNLOAD:
nbBytes = rtpManager.getGlobalReceptionStats().getBytesRecd();
nbBytes = statisticsEngine.getNbBytesReceived();
break;
case UPLOAD:
nbBytes
= rtpManager.getGlobalTransmissionStats().getBytesSent();
nbBytes = statisticsEngine.getNbBytesSent();
break;
}
}
Expand Down Expand Up @@ -985,25 +989,23 @@ public long getNbPacketsReceived()
* @param streamDirection The stream direction (DOWNLOAD or UPLOAD) of the
* stream from which this function retrieve the number of sent/received
* packets.
*
* @return the number of packets sent/received for this stream.
*/
private long getNbPDU(StreamDirection streamDirection)
{
StatisticsEngine statisticsEngine
= mediaStreamImpl.getStatisticsEngine();
// We don't use the values from the RTPManager, because they are
// incorrect when an RTPTranslator is used.
long nbPDU = 0;

StatisticsEngine statisticsEngine
= mediaStreamImpl.getStatisticsEngine();
if (statisticsEngine != null)
{
switch(streamDirection)
switch (streamDirection)
{
case UPLOAD:
nbPDU = statisticsEngine.getRtpPacketsSent();
break;

case DOWNLOAD:
nbPDU = statisticsEngine.getRtpPacketsReceived();
break;
Expand Down Expand Up @@ -1295,6 +1297,8 @@ private void updateJitterRTPTimestampUnits(
// deviation of the jitter.
jitterRTPTimestampUnits[streamDirection.ordinal()]
= feedback.getJitter();
getStats(feedback.getSSRC(), streamDirection)
.setJitter(rtpTimeToMs(feedback.getJitter()));
}

/**
Expand Down Expand Up @@ -1386,7 +1390,9 @@ private void updateNewReceivedFeedback(RTCPFeedback feedback)
// Updates the loss rate with the RTCP sender report feedback, since
// this is the only information source available for the upload stream.
long uploadNewNbRecv = feedback.getXtndSeqNum();

nbPacketsLostUpload = feedback.getNumLost();

long newNbLost
= nbPacketsLostUpload - nbLost[streamDirection.ordinal()];
long nbSteps = uploadNewNbRecv - uploadFeedbackNbPackets;
Expand All @@ -1403,6 +1409,8 @@ private void updateNewReceivedFeedback(RTCPFeedback feedback)
if (rtt >= 0)
{
setRttMs(rtt);

getStats(feedback.getSSRC(), streamDirection).setRttMs(rtt);
}
}

Expand Down Expand Up @@ -1638,4 +1646,48 @@ public long getSendingBitrate()

return sbr;
}

/**
* Returns the stat for the ssrc and direction.
* @param ssrc the ssrc
* @param streamDirection the direction.
* @return the object holding all the stats.
*/
private AbstractMediaStreamSSRCStats getStats(
long ssrc, StreamDirection streamDirection)
{
Map<Long,AbstractMediaStreamSSRCStats> stats
= mediaStreamStats[streamDirection.ordinal()];
AbstractMediaStreamSSRCStats stat = stats.get(ssrc);

if (stat == null)
{
StatisticsEngine statisticsEngine
= mediaStreamImpl.getStatisticsEngine();

if (streamDirection == StreamDirection.DOWNLOAD)
stat = new MediaStreamReceivedSSRCStats(ssrc, statisticsEngine);
else
stat = new MediaStreamSentSSRCStats(ssrc, statisticsEngine);

stats.put(ssrc, stat);
}
return stat;
}

/**
* {@inheritDoc}
*/
public Collection<? extends MediaStreamSSRCStats> getReceivedStats()
{
return mediaStreamStats[StreamDirection.DOWNLOAD.ordinal()].values();
}

/**
* {@inheritDoc}
*/
public Collection<? extends MediaStreamSSRCStats> getSentStats()
{
return mediaStreamStats[StreamDirection.UPLOAD.ordinal()].values();
}
}

0 comments on commit a16a3e6

Please sign in to comment.