From 7b7fbadfc75940239d439202be8b92a6a02a890b Mon Sep 17 00:00:00 2001 From: damencho Date: Wed, 27 Apr 2016 19:05:57 +0300 Subject: [PATCH 1/2] Adds statistics per ssrc in MediaStreamStats and their implementation. --- .../AbstractMediaStreamSSRCStats.java | 125 +++++++++++++++ .../MediaStreamReceivedSSRCStats.java | 49 ++++++ .../neomedia/MediaStreamSentSSRCStats.java | 49 ++++++ .../impl/neomedia/MediaStreamStatsImpl.java | 83 ++++++++-- .../transform/rtcp/StatisticsEngine.java | 145 ++++++++++++++++-- .../neomedia/MediaStreamSSRCStats.java | 56 +++++++ .../service/neomedia/MediaStreamStats.java | 16 ++ 7 files changed, 499 insertions(+), 24 deletions(-) create mode 100644 src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java create mode 100644 src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java create mode 100644 src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java create mode 100644 src/org/jitsi/service/neomedia/MediaStreamSSRCStats.java diff --git a/src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java b/src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java new file mode 100644 index 000000000..8073e4967 --- /dev/null +++ b/src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java @@ -0,0 +1,125 @@ +/* + * 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 ssrc send or receive. + * + * @author Damian Minkov + */ +public abstract class AbstractMediaStreamSSRCStats + implements MediaStreamSSRCStats +{ + /** + * The StatisticsEngine of this instance. + */ + protected StatisticsEngine statisticsEngine; + + /** + * The ssrc which stats are we handling. + */ + protected final long ssrc; + + /** + * The last jitter received/sent in a 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"). + * -1 if the RTT has not been computed yet. Otherwise the RTT in ms. + */ + private long rttMs = -1; + + /** + * Inits AbstractMediaStreamSSRCStats. + * @param ssrc the ssrc of the stream. + * @param statisticsEngine the stats engine instance to use. + */ + AbstractMediaStreamSSRCStats(long ssrc, StatisticsEngine statisticsEngine) + { + this.ssrc = ssrc; + this.statisticsEngine = statisticsEngine; + } + + /** + * Returns a {@code long} the SSRC of these stats. + * @return a {@code long} the SSRC of these stats. + */ + public long getSSRC() + { + return ssrc; + } + + /** + * The jitter received/sent in a RTCP feedback (in ms). + * @return the last jitter received/sent in a RTCP feedback. + */ + public double getJitter() + { + return jitter; + } + + /** + * Sets the last jitter that was sent/received. + * + * @param jitter the new value + */ + public void setJitter(double jitter) + { + this.jitter = jitter; + } + + /** + * The number of bytes sent or received by the stream. + * @return number of bytes. + */ + public abstract long getNbBytes(); + + /** + * The number of packets sent or received by the stream. + * @return number of packets. + */ + public abstract long getNbPackets(); + + /** + * Returns the RTT computed with the RTCP feedback (cf. RFC3550, section + * 6.4.1, subsection "delay since last SR (DLSR): 32 bits"). + * + * @return The RTT computed with the RTCP feedback. Returns -1 if + * the RTT has not been computed yet. Otherwise the RTT in ms. + */ + public long getRttMs() + { + return rttMs; + } + + /** + * Sets a specific value on {@link #rttMs}. If there is an actual difference + * between the old and the new values, notifies the (known) + * CallStatsObservers. + * + * @param rttMs the value to set on MediaStreamStatsImpl.rttMs + */ + public void setRttMs(long rttMs) + { + this.rttMs = rttMs; + } +} diff --git a/src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java b/src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java new file mode 100644 index 000000000..2fe2da434 --- /dev/null +++ b/src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java @@ -0,0 +1,49 @@ +/* + * 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 per received ssrc implementation. + * @author Damian Minkov + */ +public class MediaStreamReceivedSSRCStats + extends AbstractMediaStreamSSRCStats +{ + MediaStreamReceivedSSRCStats(long ssrc, StatisticsEngine statisticsEngine) + { + super(ssrc, statisticsEngine); + } + + /** + * The number of bytes received by the stream. + * @return number of bytes. + */ + public long getNbBytes() + { + return this.statisticsEngine.getNbBytesReceived(this.ssrc); + } + + /** + * The number of packets received by the stream. + * @return number of packets. + */ + public long getNbPackets() + { + return this.statisticsEngine.getRtpPacketsReceived(this.ssrc); + } +} diff --git a/src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java b/src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java new file mode 100644 index 000000000..dd9ba76ed --- /dev/null +++ b/src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java @@ -0,0 +1,49 @@ +/* + * 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 per send ssrc implementation. + * @author Damian Minkov + */ +public class MediaStreamSentSSRCStats + extends AbstractMediaStreamSSRCStats +{ + MediaStreamSentSSRCStats(long ssrc, StatisticsEngine statisticsEngine) + { + super(ssrc, statisticsEngine); + } + + /** + * The number of bytes sent by the stream. + * @return number of bytes. + */ + public long getNbBytes() + { + return this.statisticsEngine.getNbBytesSent(this.ssrc); + } + + /** + * The number of packets sent by the stream. + * @return number of packets. + */ + public long getNbPackets() + { + return this.statisticsEngine.getRtpPacketsSent(this.ssrc); + } +} diff --git a/src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java b/src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java index 5661f0164..528837354 100644 --- a/src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java +++ b/src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java @@ -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.*; @@ -67,6 +66,12 @@ private enum StreamDirection private static final Logger logger = Logger.getLogger(MediaStreamStatsImpl.class); + /** + * List of stats per ssrc. + */ + private Map[] 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 @@ -832,21 +837,21 @@ public int getLocalPort() */ private long getNbBytes(StreamDirection streamDirection) { - StreamRTPManager rtpManager = mediaStreamImpl.queryRTPManager(); + if(mediaStreamImpl.getStatisticsEngine() == null) + return 0; + long nbBytes = 0; - if(rtpManager != null) + switch(streamDirection) { - switch(streamDirection) - { - case DOWNLOAD: - nbBytes = rtpManager.getGlobalReceptionStats().getBytesRecd(); - break; - case UPLOAD: - nbBytes - = rtpManager.getGlobalTransmissionStats().getBytesSent(); - break; - } + case DOWNLOAD: + nbBytes = mediaStreamImpl + .getStatisticsEngine().getNbBytesReceived(); + break; + case UPLOAD: + nbBytes + = mediaStreamImpl.getStatisticsEngine().getNbBytesSent(); + break; } return nbBytes; } @@ -1006,7 +1011,6 @@ private long getNbPDU(StreamDirection streamDirection) case DOWNLOAD: nbPDU = statisticsEngine.getRtpPacketsReceived(); - break; } } return nbPDU; @@ -1295,6 +1299,8 @@ private void updateJitterRTPTimestampUnits( // deviation of the jitter. jitterRTPTimestampUnits[streamDirection.ordinal()] = feedback.getJitter(); + getStats(feedback.getSSRC(), streamDirection) + .setJitter(rtpTimeToMs(feedback.getJitter())); } /** @@ -1403,6 +1409,9 @@ private void updateNewReceivedFeedback(RTCPFeedback feedback) if (rtt >= 0) { setRttMs(rtt); + + getStats( + feedback.getSSRC(), streamDirection).setRttMs(rtt); } } @@ -1638,4 +1647,50 @@ 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) + { + AbstractMediaStreamSSRCStats stat = + mediaStreamStats[streamDirection.ordinal()].get(ssrc); + if(stat == null) + { + if (streamDirection == StreamDirection.DOWNLOAD) + stat = new MediaStreamReceivedSSRCStats( + ssrc, mediaStreamImpl.getStatisticsEngine()); + else + stat = new MediaStreamSentSSRCStats( + ssrc, mediaStreamImpl.getStatisticsEngine()); + + mediaStreamStats[streamDirection.ordinal()].put(ssrc, stat); + } + + return stat; + } + + /** + * Returns the receive stats. + * + * @return the list holding all the stats. + */ + public Collection getReceivedStats() + { + return mediaStreamStats[StreamDirection.DOWNLOAD.ordinal()].values(); + } + + /** + * Returns the sent stats. + * + * @return the list holding all the stats. + */ + public Collection getSentStats() + { + return mediaStreamStats[StreamDirection.UPLOAD.ordinal()].values(); + } } diff --git a/src/org/jitsi/impl/neomedia/transform/rtcp/StatisticsEngine.java b/src/org/jitsi/impl/neomedia/transform/rtcp/StatisticsEngine.java index 6ea346975..5a6487eeb 100644 --- a/src/org/jitsi/impl/neomedia/transform/rtcp/StatisticsEngine.java +++ b/src/org/jitsi/impl/neomedia/transform/rtcp/StatisticsEngine.java @@ -145,24 +145,39 @@ private static boolean isRTCP(RawPacket pkt) /** * The number of RTCP sender reports (SR) and/or receiver reports (RR) sent. + * Mapped per ssrc. */ - private long numberOfRTCPReports = 0; + private Map numberOfRTCPReportsMap = new HashMap<>(); /** * The sum of the jitter values we have reported in RTCP reports, in RTP * timestamp units. */ - private long jitterSum = 0; + private Map jitterSumMap = new HashMap<>(); /** * The number of RTP packets sent though this instance. + * Mapped per ssrc. */ - private long rtpPacketsSent = 0; + private Map rtpPacketsSentMap = new HashMap<>(); /** * The number of RTP packets sent though this instance. + * Mapped per ssrc. */ - private long rtpPacketsReceived = 0; + private Map rtpPacketsReceivedMap = new HashMap<>(); + + /** + * The bytes of RTP packets sent though this instance. + * Mapped per ssrc. + */ + private Map rtpBytesSentMap = new HashMap<>(); + + /** + * The bytes of RTP packets sent though this instance. + * Mapped per ssrc. + */ + private Map rtpBytesReceivedMap = new HashMap<>(); /** * The {@link RTCPPacketParserEx} which this instance will use to parse @@ -186,14 +201,30 @@ private static boolean isRTCP(RawPacket pkt) @Override public RawPacket transform(RawPacket pkt) { - StatisticsEngine.this.rtpPacketsSent++; + incrementSSRCCounter( + StatisticsEngine.this.rtpPacketsSentMap, + pkt.getSSRCAsLong(), + 1); + incrementSSRCCounter( + StatisticsEngine.this.rtpBytesSentMap, + pkt.getSSRCAsLong(), + pkt.getLength()); + return pkt; } @Override public RawPacket reverseTransform(RawPacket pkt) { - StatisticsEngine.this.rtpPacketsReceived++; + incrementSSRCCounter( + StatisticsEngine.this.rtpPacketsReceivedMap, + pkt.getSSRCAsLong(), + 1); + incrementSSRCCounter( + StatisticsEngine.this.rtpBytesReceivedMap, + pkt.getSSRCAsLong(), + pkt.getLength()); + return pkt; } }; @@ -829,6 +860,9 @@ public long getMaxInterArrivalJitter() */ public double getAvgInterArrivalJitter() { + long numberOfRTCPReports = getCumulativeValue(numberOfRTCPReportsMap); + long jitterSum = getCumulativeValue(jitterSumMap); + return numberOfRTCPReports == 0 ? 0 @@ -1214,7 +1248,8 @@ private void updateSentMediaStreamStats(RawPacket pkt) = (RTCPFeedback) feedbackReports.get(0); long jitter = feedback.getJitter(); - numberOfRTCPReports++; + incrementSSRCCounter( + numberOfRTCPReportsMap, feedback.getSSRC(), 1); if ((jitter < getMinInterArrivalJitter()) || (getMinInterArrivalJitter() == -1)) @@ -1222,12 +1257,14 @@ private void updateSentMediaStreamStats(RawPacket pkt) if (getMaxInterArrivalJitter() < jitter) maxInterArrivalJitter = jitter; - jitterSum += jitter; + incrementSSRCCounter(jitterSumMap, feedback.getSSRC(), jitter); lost = feedback.getNumLost(); if(logger.isTraceEnabled()) { + long numberOfRTCPReports + = numberOfRTCPReportsMap.get(feedback.getSSRC()); // As sender reports are sent on every 5 seconds, print // every 4th packet, on every 20 seconds. if(numberOfRTCPReports % 4 == 1) @@ -1270,7 +1307,7 @@ private void updateSentMediaStreamStats(RawPacket pkt) */ public long getRtpPacketsSent() { - return rtpPacketsSent; + return getCumulativeValue(rtpPacketsSentMap); } /** @@ -1279,6 +1316,94 @@ public long getRtpPacketsSent() */ public long getRtpPacketsReceived() { - return rtpPacketsReceived; + return getCumulativeValue(rtpPacketsReceivedMap); + } + + /** + * Gets the number of RTP packets sent for a stream with the ssrc. + * @return the number of RTP packets sent for a stream with the ssrc. + */ + public long getRtpPacketsSent(long ssrc) + { + return rtpPacketsSentMap.get(ssrc); + } + + /** + * Gets the number of RTP packets received for a stream with the ssrc. + * @return the number of RTP packets received for a stream with the ssrc. + */ + public long getRtpPacketsReceived(long ssrc) + { + return rtpPacketsReceivedMap.get(ssrc); + } + + /** + * Utility method to accumulate values stored in the map. + * @param map the map which values will be + * @return + */ + private static long getCumulativeValue(Map map) + { + long accumulatedValues = 0; + for (Map.Entry en : map.entrySet()) + { + accumulatedValues += en.getValue(); + } + return accumulatedValues; + } + + /** + * Utility method to increment map value with specified step. If entry is + * missing add it. + * @param map the map holding the values + * @param ssrc the key of the value to increment + * @param step increment step value + */ + private static void incrementSSRCCounter( + Map map, long ssrc, long step) + { + Long count = map.get(ssrc); + if(count == null) + map.put(ssrc, step); + else + map.put(ssrc, count + step); + } + + /** + * Returns the number of bytes received for a stream with the ssrc. + * @param ssrc the stream ssrc + * @return number of bytes per stream. + */ + public long getNbBytesReceived(long ssrc) + { + return rtpBytesReceivedMap.get(ssrc); + } + + /** + * Returns the number of bytes sent by a stream with the ssrc. + * @param ssrc the stream ssrc + * @return number of bytes per stream. + */ + public long getNbBytesSent(long ssrc) + { + return rtpBytesSentMap.get(ssrc); + } + + /** + * Returns the number of bytes received for all streams. + * @return number of bytes for all stream. + */ + public long getNbBytesReceived() + { + return getCumulativeValue(rtpBytesReceivedMap); + } + + /** + * Returns the number of bytes sent by all streams. + * @return number of bytes for all stream. + */ + public long getNbBytesSent() + { + return getCumulativeValue(rtpBytesSentMap); } } diff --git a/src/org/jitsi/service/neomedia/MediaStreamSSRCStats.java b/src/org/jitsi/service/neomedia/MediaStreamSSRCStats.java new file mode 100644 index 000000000..687169bee --- /dev/null +++ b/src/org/jitsi/service/neomedia/MediaStreamSSRCStats.java @@ -0,0 +1,56 @@ +/* + * 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.service.neomedia; + +/** + * Media stream statistics per ssrc. + * @author Damian Minkov + */ +public interface MediaStreamSSRCStats +{ + /** + * Returns a {@code long} the SSRC of these stats. + * @return a {@code long} the SSRC of these stats. + */ + public long getSSRC(); + + /** + * The jitter received/sent in a RTCP feedback (in ms). + * @return the last jitter received/sent in a RTCP feedback. + */ + public double getJitter(); + + /** + * The number of bytes sent or received by the stream. + * @return number of bytes. + */ + public long getNbBytes(); + + /** + * The number of packets sent or received by the stream. + * @return number of packets. + */ + public long getNbPackets(); + + /** + * Returns the RTT computed with the RTCP feedback (cf. RFC3550, section + * 6.4.1, subsection "delay since last SR (DLSR): 32 bits"). + * + * @return The RTT computed with the RTCP feedback. Returns -1 if + * the RTT has not been computed yet. Otherwise the RTT in ms. + */ + public long getRttMs(); +} diff --git a/src/org/jitsi/service/neomedia/MediaStreamStats.java b/src/org/jitsi/service/neomedia/MediaStreamStats.java index 082c56d2b..707aec21d 100644 --- a/src/org/jitsi/service/neomedia/MediaStreamStats.java +++ b/src/org/jitsi/service/neomedia/MediaStreamStats.java @@ -17,6 +17,8 @@ import java.awt.*; +import java.util.*; + import org.jitsi.service.neomedia.rtp.*; /** @@ -378,4 +380,18 @@ public interface MediaStreamStats * endpoint, in bits per second. */ public long getSendingBitrate(); + + /** + * Returns the receive stats. + * + * @return the list holding all the stats. + */ + public Collection getReceivedStats(); + + /** + * Returns the sent stats. + * + * @return the list holding all the stats. + */ + public Collection getSentStats(); } From 4abbd340f6176b8afb6cd545bfde7d4c2e29ba51 Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Thu, 12 May 2016 10:43:55 -0500 Subject: [PATCH 2/2] Fix, format, simplify javadocs, source code --- .../AbstractMediaStreamSSRCStats.java | 53 +++---- .../MediaStreamReceivedSSRCStats.java | 13 +- .../neomedia/MediaStreamSentSSRCStats.java | 13 +- .../impl/neomedia/MediaStreamStatsImpl.java | 71 +++++---- .../transform/rtcp/StatisticsEngine.java | 136 +++++++++--------- .../neomedia/MediaStreamSSRCStats.java | 31 ++-- .../service/neomedia/MediaStreamStats.java | 7 +- 7 files changed, 158 insertions(+), 166 deletions(-) diff --git a/src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java b/src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java index 8073e4967..78cbbbbdb 100644 --- a/src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java +++ b/src/org/jitsi/impl/neomedia/AbstractMediaStreamSSRCStats.java @@ -19,7 +19,7 @@ import org.jitsi.service.neomedia.*; /** - * Media stream statistics per ssrc send or receive. + * Media stream statistics per send or receive SSRC. * * @author Damian Minkov */ @@ -29,29 +29,31 @@ public abstract class AbstractMediaStreamSSRCStats /** * The StatisticsEngine of this instance. */ - protected StatisticsEngine statisticsEngine; + protected final StatisticsEngine statisticsEngine; /** - * The ssrc which stats are we handling. + * The SSRC of this piece of statistics. */ protected final long ssrc; /** - * The last jitter received/sent in a RTCP feedback (in ms). + * 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"). - * -1 if the RTT has not been computed yet. Otherwise the RTT in ms. + * 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; /** - * Inits AbstractMediaStreamSSRCStats. - * @param ssrc the ssrc of the stream. - * @param statisticsEngine the stats engine instance to use. + * 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) { @@ -60,8 +62,7 @@ public abstract class AbstractMediaStreamSSRCStats } /** - * Returns a {@code long} the SSRC of these stats. - * @return a {@code long} the SSRC of these stats. + * {@inheritDoc} */ public long getSSRC() { @@ -69,8 +70,7 @@ public long getSSRC() } /** - * The jitter received/sent in a RTCP feedback (in ms). - * @return the last jitter received/sent in a RTCP feedback. + * {@inheritDoc} */ public double getJitter() { @@ -80,7 +80,8 @@ public double getJitter() /** * Sets the last jitter that was sent/received. * - * @param jitter the new value + * @param jitter the new value to set on this instance as the last + * sent/received jitter */ public void setJitter(double jitter) { @@ -88,23 +89,7 @@ public void setJitter(double jitter) } /** - * The number of bytes sent or received by the stream. - * @return number of bytes. - */ - public abstract long getNbBytes(); - - /** - * The number of packets sent or received by the stream. - * @return number of packets. - */ - public abstract long getNbPackets(); - - /** - * Returns the RTT computed with the RTCP feedback (cf. RFC3550, section - * 6.4.1, subsection "delay since last SR (DLSR): 32 bits"). - * - * @return The RTT computed with the RTCP feedback. Returns -1 if - * the RTT has not been computed yet. Otherwise the RTT in ms. + * {@inheritDoc} */ public long getRttMs() { @@ -112,11 +97,9 @@ public long getRttMs() } /** - * Sets a specific value on {@link #rttMs}. If there is an actual difference - * between the old and the new values, notifies the (known) - * CallStatsObservers. + * Sets a specific value on {@link #rttMs}. * - * @param rttMs the value to set on MediaStreamStatsImpl.rttMs + * @param rttMs the new value to set on {@link #rttMs} */ public void setRttMs(long rttMs) { diff --git a/src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java b/src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java index 2fe2da434..097f2b81a 100644 --- a/src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java +++ b/src/org/jitsi/impl/neomedia/MediaStreamReceivedSSRCStats.java @@ -18,7 +18,8 @@ import org.jitsi.impl.neomedia.transform.rtcp.*; /** - * Media stream statistics per received ssrc implementation. + * Media stream statistics implementation per received SSRC. + * * @author Damian Minkov */ public class MediaStreamReceivedSSRCStats @@ -30,20 +31,18 @@ public class MediaStreamReceivedSSRCStats } /** - * The number of bytes received by the stream. - * @return number of bytes. + * {@inheritDoc} */ public long getNbBytes() { - return this.statisticsEngine.getNbBytesReceived(this.ssrc); + return statisticsEngine.getNbBytesReceived(ssrc); } /** - * The number of packets received by the stream. - * @return number of packets. + * {@inheritDoc} */ public long getNbPackets() { - return this.statisticsEngine.getRtpPacketsReceived(this.ssrc); + return statisticsEngine.getRtpPacketsReceived(ssrc); } } diff --git a/src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java b/src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java index dd9ba76ed..13ed7b8af 100644 --- a/src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java +++ b/src/org/jitsi/impl/neomedia/MediaStreamSentSSRCStats.java @@ -18,7 +18,8 @@ import org.jitsi.impl.neomedia.transform.rtcp.*; /** - * Media stream statistics per send ssrc implementation. + * Media stream statistics implementation per send SSRC. + * * @author Damian Minkov */ public class MediaStreamSentSSRCStats @@ -30,20 +31,18 @@ public class MediaStreamSentSSRCStats } /** - * The number of bytes sent by the stream. - * @return number of bytes. + * {@inheritDoc} */ public long getNbBytes() { - return this.statisticsEngine.getNbBytesSent(this.ssrc); + return statisticsEngine.getNbBytesSent(ssrc); } /** - * The number of packets sent by the stream. - * @return number of packets. + * {@inheritDoc} */ public long getNbPackets() { - return this.statisticsEngine.getRtpPacketsSent(this.ssrc); + return statisticsEngine.getRtpPacketsSent(ssrc); } } diff --git a/src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java b/src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java index 528837354..052ba8101 100644 --- a/src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java +++ b/src/org/jitsi/impl/neomedia/MediaStreamStatsImpl.java @@ -69,8 +69,8 @@ private enum StreamDirection /** * List of stats per ssrc. */ - private Map[] mediaStreamStats = - new Map[] {new HashMap<>(), new HashMap<>()}; + private final Map[] mediaStreamStats + = new Map[] { new HashMap<>(), new HashMap<>() }; /** * Computes an Exponentially Weighted Moving Average (EWMA). Thus, the most @@ -832,26 +832,25 @@ 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) { - if(mediaStreamImpl.getStatisticsEngine() == null) - return 0; - + StatisticsEngine statisticsEngine + = mediaStreamImpl.getStatisticsEngine(); long nbBytes = 0; - switch(streamDirection) + if (statisticsEngine != null) { - case DOWNLOAD: - nbBytes = mediaStreamImpl - .getStatisticsEngine().getNbBytesReceived(); - break; - case UPLOAD: - nbBytes - = mediaStreamImpl.getStatisticsEngine().getNbBytesSent(); - break; + switch (streamDirection) + { + case DOWNLOAD: + nbBytes = statisticsEngine.getNbBytesReceived(); + break; + case UPLOAD: + nbBytes = statisticsEngine.getNbBytesSent(); + break; + } } return nbBytes; } @@ -990,27 +989,26 @@ 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; } } return nbPDU; @@ -1392,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; @@ -1410,8 +1410,7 @@ private void updateNewReceivedFeedback(RTCPFeedback feedback) { setRttMs(rtt); - getStats( - feedback.getSSRC(), streamDirection).setRttMs(rtt); + getStats(feedback.getSSRC(), streamDirection).setRttMs(rtt); } } @@ -1657,27 +1656,27 @@ public long getSendingBitrate() private AbstractMediaStreamSSRCStats getStats( long ssrc, StreamDirection streamDirection) { - AbstractMediaStreamSSRCStats stat = - mediaStreamStats[streamDirection.ordinal()].get(ssrc); - if(stat == null) + Map stats + = mediaStreamStats[streamDirection.ordinal()]; + AbstractMediaStreamSSRCStats stat = stats.get(ssrc); + + if (stat == null) { + StatisticsEngine statisticsEngine + = mediaStreamImpl.getStatisticsEngine(); + if (streamDirection == StreamDirection.DOWNLOAD) - stat = new MediaStreamReceivedSSRCStats( - ssrc, mediaStreamImpl.getStatisticsEngine()); + stat = new MediaStreamReceivedSSRCStats(ssrc, statisticsEngine); else - stat = new MediaStreamSentSSRCStats( - ssrc, mediaStreamImpl.getStatisticsEngine()); + stat = new MediaStreamSentSSRCStats(ssrc, statisticsEngine); - mediaStreamStats[streamDirection.ordinal()].put(ssrc, stat); + stats.put(ssrc, stat); } - return stat; } /** - * Returns the receive stats. - * - * @return the list holding all the stats. + * {@inheritDoc} */ public Collection getReceivedStats() { @@ -1685,9 +1684,7 @@ public Collection getReceivedStats() } /** - * Returns the sent stats. - * - * @return the list holding all the stats. + * {@inheritDoc} */ public Collection getSentStats() { diff --git a/src/org/jitsi/impl/neomedia/transform/rtcp/StatisticsEngine.java b/src/org/jitsi/impl/neomedia/transform/rtcp/StatisticsEngine.java index 5a6487eeb..fcf4beb00 100644 --- a/src/org/jitsi/impl/neomedia/transform/rtcp/StatisticsEngine.java +++ b/src/org/jitsi/impl/neomedia/transform/rtcp/StatisticsEngine.java @@ -147,37 +147,37 @@ private static boolean isRTCP(RawPacket pkt) * The number of RTCP sender reports (SR) and/or receiver reports (RR) sent. * Mapped per ssrc. */ - private Map numberOfRTCPReportsMap = new HashMap<>(); + private final Map numberOfRTCPReportsMap = new HashMap<>(); /** * The sum of the jitter values we have reported in RTCP reports, in RTP * timestamp units. */ - private Map jitterSumMap = new HashMap<>(); + private final Map jitterSumMap = new HashMap<>(); /** * The number of RTP packets sent though this instance. * Mapped per ssrc. */ - private Map rtpPacketsSentMap = new HashMap<>(); + private final Map rtpPacketsSentMap = new HashMap<>(); /** * The number of RTP packets sent though this instance. * Mapped per ssrc. */ - private Map rtpPacketsReceivedMap = new HashMap<>(); + private final Map rtpPacketsReceivedMap = new HashMap<>(); /** * The bytes of RTP packets sent though this instance. * Mapped per ssrc. */ - private Map rtpBytesSentMap = new HashMap<>(); + private final Map rtpBytesSentMap = new HashMap<>(); /** * The bytes of RTP packets sent though this instance. * Mapped per ssrc. */ - private Map rtpBytesReceivedMap = new HashMap<>(); + private final Map rtpBytesReceivedMap = new HashMap<>(); /** * The {@link RTCPPacketParserEx} which this instance will use to parse @@ -196,38 +196,42 @@ private static boolean isRTCP(RawPacket pkt) * packets. */ private final PacketTransformer rtpTransformer - = new SinglePacketTransformer(RTPPacketPredicate.INSTANCE) - { - @Override - public RawPacket transform(RawPacket pkt) + = new SinglePacketTransformer(RTPPacketPredicate.INSTANCE) { - incrementSSRCCounter( - StatisticsEngine.this.rtpPacketsSentMap, - pkt.getSSRCAsLong(), - 1); - incrementSSRCCounter( - StatisticsEngine.this.rtpBytesSentMap, - pkt.getSSRCAsLong(), - pkt.getLength()); - - return pkt; - } + @Override + public RawPacket transform(RawPacket pkt) + { + long ssrc = pkt.getSSRCAsLong(); - @Override - public RawPacket reverseTransform(RawPacket pkt) - { - incrementSSRCCounter( - StatisticsEngine.this.rtpPacketsReceivedMap, - pkt.getSSRCAsLong(), - 1); - incrementSSRCCounter( - StatisticsEngine.this.rtpBytesReceivedMap, - pkt.getSSRCAsLong(), - pkt.getLength()); - - return pkt; - } - }; + incrementSSRCCounter( + StatisticsEngine.this.rtpPacketsSentMap, + ssrc, + 1); + incrementSSRCCounter( + StatisticsEngine.this.rtpBytesSentMap, + ssrc, + pkt.getLength()); + + return pkt; + } + + @Override + public RawPacket reverseTransform(RawPacket pkt) + { + long ssrc = pkt.getSSRCAsLong(); + + incrementSSRCCounter( + StatisticsEngine.this.rtpPacketsReceivedMap, + ssrc, + 1); + incrementSSRCCounter( + StatisticsEngine.this.rtpBytesReceivedMap, + ssrc, + pkt.getLength()); + + return pkt; + } + }; /** * Creates Statistic engine. @@ -1244,27 +1248,27 @@ private void updateSentMediaStreamStats(RawPacket pkt) if(!feedbackReports.isEmpty()) { - RTCPFeedback feedback - = (RTCPFeedback) feedbackReports.get(0); + RTCPFeedback feedback = (RTCPFeedback) feedbackReports.get(0); + long ssrc = feedback.getSSRC(); long jitter = feedback.getJitter(); - incrementSSRCCounter( - numberOfRTCPReportsMap, feedback.getSSRC(), 1); + incrementSSRCCounter(numberOfRTCPReportsMap, ssrc, 1); - if ((jitter < getMinInterArrivalJitter()) - || (getMinInterArrivalJitter() == -1)) + if (jitter < getMinInterArrivalJitter() + || getMinInterArrivalJitter() == -1) + { minInterArrivalJitter = jitter; + } if (getMaxInterArrivalJitter() < jitter) maxInterArrivalJitter = jitter; - incrementSSRCCounter(jitterSumMap, feedback.getSSRC(), jitter); + incrementSSRCCounter(jitterSumMap, ssrc, jitter); lost = feedback.getNumLost(); if(logger.isTraceEnabled()) { - long numberOfRTCPReports - = numberOfRTCPReportsMap.get(feedback.getSSRC()); + long numberOfRTCPReports = numberOfRTCPReportsMap.get(ssrc); // As sender reports are sent on every 5 seconds, print // every 4th packet, on every 20 seconds. if(numberOfRTCPReports % 4 == 1) @@ -1274,25 +1278,23 @@ private void updateSentMediaStreamStats(RawPacket pkt) = (mediaType == null) ? "" : mediaType.toString(); buff.append("Sending a report for ") - .append(mediaTypeStr) - .append(" stream SSRC:").append(feedback.getSSRC()) - .append(" ["); + .append(mediaTypeStr).append(" stream SSRC:") + .append(ssrc).append(" ["); // SR includes sender info, RR does not. if (r instanceof RTCPSenderReport) { RTCPSenderReport sr = (RTCPSenderReport) r; buff.append("packet count:") - .append(sr.getSenderPacketCount()) + .append(sr.getSenderPacketCount()) .append(", bytes:") - .append(sr.getSenderByteCount()) - .append(", "); + .append(sr.getSenderByteCount()).append(", "); } buff.append("interarrival jitter:").append(jitter) .append(", lost packets:") - .append(feedback.getNumLost()) + .append(feedback.getNumLost()) .append(", time since previous report:") - .append((int) (feedback.getDLSR() / 65.536)) + .append((int) (feedback.getDLSR() / 65.536)) .append("ms]"); logger.trace(buff); } @@ -1338,35 +1340,39 @@ public long getRtpPacketsReceived(long ssrc) } /** - * Utility method to accumulate values stored in the map. - * @param map the map which values will be - * @return + * Computes the sum of the values of a specific {@code Map} with + * {@code Long} values. + * + * @param map the {@code Map} with {@code Long} values to sum up + * @return the sum of the values of the specified {@code map} */ private static long getCumulativeValue(Map map) { - long accumulatedValues = 0; - for (Map.Entry en : map.entrySet()) + long cumulativeValue = 0; + + for (Long value : map.values()) { - accumulatedValues += en.getValue(); + cumulativeValue += value; } - return accumulatedValues; + return cumulativeValue; } /** * Utility method to increment map value with specified step. If entry is * missing add it. + * * @param map the map holding the values * @param ssrc the key of the value to increment * @param step increment step value */ private static void incrementSSRCCounter( - Map map, long ssrc, long step) + Map map, + long ssrc, + long step) { Long count = map.get(ssrc); - if(count == null) - map.put(ssrc, step); - else - map.put(ssrc, count + step); + + map.put(ssrc, (count == null) ? step : (count + step)); } /** diff --git a/src/org/jitsi/service/neomedia/MediaStreamSSRCStats.java b/src/org/jitsi/service/neomedia/MediaStreamSSRCStats.java index 687169bee..f3a8faea7 100644 --- a/src/org/jitsi/service/neomedia/MediaStreamSSRCStats.java +++ b/src/org/jitsi/service/neomedia/MediaStreamSSRCStats.java @@ -16,32 +16,41 @@ package org.jitsi.service.neomedia; /** - * Media stream statistics per ssrc. + * Media stream statistics per SSRC. + * * @author Damian Minkov */ public interface MediaStreamSSRCStats { /** - * Returns a {@code long} the SSRC of these stats. - * @return a {@code long} the SSRC of these stats. + * Returns the SSRC of these stats (as a {@code long} value). + * + * @return a {@code long} value which represents the SSRC of these stats. */ public long getSSRC(); /** - * The jitter received/sent in a RTCP feedback (in ms). - * @return the last jitter received/sent in a RTCP feedback. + * The jitter received/sent in an RTCP feedback (in milliseconds). + * + * @return the last jitter received/sent in an RTCP feedback. */ public double getJitter(); /** - * The number of bytes sent or received by the stream. - * @return number of bytes. + * The number of bytes sent or received by the associated + * {@code MediaStream}. + * + * @return the number of bytes sent or received by the associated + * {@code MediaStream}. */ public long getNbBytes(); /** - * The number of packets sent or received by the stream. - * @return number of packets. + * The number of packets sent or received by the associated + * {@code MediaStream}. + * + * @return the number of packets sent or received by the associated + * {@code MediaStream}. */ public long getNbPackets(); @@ -49,8 +58,8 @@ public interface MediaStreamSSRCStats * Returns the RTT computed with the RTCP feedback (cf. RFC3550, section * 6.4.1, subsection "delay since last SR (DLSR): 32 bits"). * - * @return The RTT computed with the RTCP feedback. Returns -1 if - * the RTT has not been computed yet. Otherwise the RTT in ms. + * @return the RTT computed with the RTCP feedback. Returns -1 if + * the RTT has not been computed yet. Otherwise, the RTT in milliseconds. */ public long getRttMs(); } diff --git a/src/org/jitsi/service/neomedia/MediaStreamStats.java b/src/org/jitsi/service/neomedia/MediaStreamStats.java index 707aec21d..1840e34cc 100644 --- a/src/org/jitsi/service/neomedia/MediaStreamStats.java +++ b/src/org/jitsi/service/neomedia/MediaStreamStats.java @@ -16,7 +16,6 @@ package org.jitsi.service.neomedia; import java.awt.*; - import java.util.*; import org.jitsi.service.neomedia.rtp.*; @@ -382,16 +381,16 @@ public interface MediaStreamStats public long getSendingBitrate(); /** - * Returns the receive stats. + * Returns the received stats. * - * @return the list holding all the stats. + * @return a list holding all received stats. */ public Collection getReceivedStats(); /** * Returns the sent stats. * - * @return the list holding all the stats. + * @return a list holding all sent stats. */ public Collection getSentStats(); }