aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator
diff options
context:
space:
mode:
authorDamian Minkov <damencho@jitsi.org>2010-12-16 07:34:31 +0000
committerDamian Minkov <damencho@jitsi.org>2010-12-16 07:34:31 +0000
commit2a29e3645e1729aa668892df5732f1463a60835d (patch)
treec771a95eda989d87aaa5e09470a63fe0b120c706 /src/net/java/sip/communicator
parent8a23901ba4e2554f11fc47c8ad3500e92e5e773f (diff)
downloadjitsi-2a29e3645e1729aa668892df5732f1463a60835d.zip
jitsi-2a29e3645e1729aa668892df5732f1463a60835d.tar.gz
jitsi-2a29e3645e1729aa668892df5732f1463a60835d.tar.bz2
Update media statistics.
Diffstat (limited to 'src/net/java/sip/communicator')
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java170
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/transform/rtcp/StatisticsEngine.java183
2 files changed, 291 insertions, 62 deletions
diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
index 8871484..ff5cd2d 100644
--- a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
@@ -26,6 +26,7 @@ import net.java.sip.communicator.impl.neomedia.format.*;
import net.java.sip.communicator.impl.neomedia.transform.*;
import net.java.sip.communicator.impl.neomedia.transform.csrc.*;
import net.java.sip.communicator.impl.neomedia.transform.dtmf.*;
+import net.java.sip.communicator.impl.neomedia.transform.rtcp.*;
import net.java.sip.communicator.impl.neomedia.transform.zrtp.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.device.*;
@@ -204,6 +205,28 @@ public class MediaStreamImpl
private boolean zrtpRestarted = false;
/**
+ * Number of received sender reports.
+ * Used only for logging and debug purposes.
+ */
+ private long numberOfReceivedSenderReports = 0;
+
+ /**
+ * The minimum inter arrival jitter value the other party has reported.
+ */
+ private long maxRemoteInterArrivalJitter = 0;
+
+ /**
+ * The maximum inter arrival jitter value the other party has reported.
+ */
+ private long minRemoteInterArrivalJitter = -1;
+
+ /**
+ * Engine chain reading sent RTCP sender reports and stores/prints
+ * statistics.
+ */
+ private StatisticsEngine statisticsEngine = null;
+
+ /**
* Initializes a new <tt>MediaStreamImpl</tt> instance which will use the
* specified <tt>MediaDevice</tt> for both capture and playback of media.
* The new instance will not have an associated <tt>StreamConnector</tt> and
@@ -330,6 +353,11 @@ public class MediaStreamImpl
// ZRTP
engineChain.add(zrtpControl.getZrtpEngine());
+ // RTCP Statistics
+ if(statisticsEngine == null)
+ statisticsEngine = new StatisticsEngine();
+ engineChain.add(statisticsEngine);
+
return
new TransformEngineChain(
engineChain.toArray(
@@ -2036,42 +2064,43 @@ public class MediaStreamImpl
if(remoteEvent instanceof SenderReportEvent)
{
+ numberOfReceivedSenderReports++;
+
SenderReport report =
((SenderReportEvent)remoteEvent).getReport();
if(report.getFeedbackReports().size() > 0)
{
+ Feedback feedback =
+ (Feedback)report.getFeedbackReports().get(0);
+
+ long remoteJitter = feedback.getJitter();
+
+ if(remoteJitter < minRemoteInterArrivalJitter
+ ||minRemoteInterArrivalJitter == -1)
+ minRemoteInterArrivalJitter = remoteJitter;
+
+ if(maxRemoteInterArrivalJitter < remoteJitter)
+ maxRemoteInterArrivalJitter = remoteJitter;
+
+ // As sender reports are received on every 5 seconds
+ // print every 4th packet, on every 20 seconds
+ if(numberOfReceivedSenderReports%4 != 1)
+ return;
- Iterator iter = report.getFeedbackReports().iterator();
- while(iter.hasNext())
- {
- Feedback feedback = (Feedback)iter.next();
-
- StringBuilder buff = new StringBuilder(
- "SenderReport (for stream ")
- .append(hashCode())
- .append(") [packetCount:");
-
- buff.append(report.getSenderPacketCount())
- .append(", bytes:").append(report.getSenderByteCount())
- .append(", interarrival jitter:")
- .append(feedback.getJitter())
- .append(", lost:").append(feedback.getNumLost())
- .append(", lastSRBefore:")
- .append((int)(feedback.getDLSR()/65.536))
- .append("ms ]");
- logger.trace(buff.toString());
- }
- }
- else
- {
StringBuilder buff = new StringBuilder(
- "SenderReport (for stream ")
- .append(hashCode())
- .append(") [packetCount:");
+ "Remote party report received (for stream ")
+ .append(hashCode())
+ .append(") [packetCount:");
buff.append(report.getSenderPacketCount())
- .append(", bytes:").append(report.getSenderByteCount());
+ .append(", bytes:").append(report.getSenderByteCount())
+ .append(", interarrival jitter:")
+ .append(remoteJitter)
+ .append(", lost:").append(feedback.getNumLost())
+ .append(", lastSRBefore:")
+ .append((int)(feedback.getDLSR()/65.536))
+ .append("ms ]");
logger.trace(buff.toString());
}
}
@@ -2163,40 +2192,57 @@ public class MediaStreamImpl
*/
private void printFlowStatistics(RTPManager rtpManager)
{
- String rtpManagerDescription = "stream " + hashCode();
-
- //print flow statistics.
- GlobalTransmissionStats s = rtpManager.getGlobalTransmissionStats();
-
- logger.trace(
- "global transmission stats (" + rtpManagerDescription + "): \n" +
- "bytes sent: " + s.getBytesSent() + "\n" +
- "local colls: " + s.getLocalColls() + "\n" +
- "remote colls: " + s.getRemoteColls() + "\n" +
- "RTCP sent: " + s.getRTCPSent() + "\n" +
- "RTP sent: " + s.getRTPSent() + "\n" +
- "transmit failed: " + s.getTransmitFailed()
- );
-
- GlobalReceptionStats rs = rtpManager.getGlobalReceptionStats();
-
- logger.trace(
- "global reception stats (" + rtpManagerDescription + "): \n" +
- "bad RTCP packets: " + rs.getBadRTCPPkts() + "\n" +
- "bad RTP packets: " + rs.getBadRTPkts() + "\n" +
- "bytes received: " + rs.getBytesRecd() + "\n" +
- "local collisions: " + rs.getLocalColls() + "\n" +
- "malformed BYEs: " + rs.getMalformedBye() + "\n" +
- "malformed RRs: " + rs.getMalformedRR() + "\n" +
- "malformed SDESs: " + rs.getMalformedSDES() + "\n" +
- "malformed SRs: " + rs.getMalformedSR() + "\n" +
- "packets looped: " + rs.getPacketsLooped() + "\n" +
- "packets received: " + rs.getPacketsRecd() + "\n" +
- "remote collisions: " + rs.getRemoteColls() + "\n" +
- "RTCPs received: " + rs.getRTCPRecd() + "\n" +
- "SRRs received: " + rs.getSRRecd() + "\n" +
- "transmit failed: " + rs.getTransmitFailed() + "\n" +
- "unknown types: " + rs.getUnknownTypes()
- );
+ try
+ {
+ String rtpManagerDescription = "stream " + hashCode();
+
+ //print flow statistics.
+ GlobalTransmissionStats s = rtpManager.getGlobalTransmissionStats();
+
+ logger.trace(
+ "global transmission stats (" + rtpManagerDescription + "): \n" +
+ "bytes sent: " + s.getBytesSent() + "\n" +
+ "RTP sent: " + s.getRTPSent() + "\n" +
+ "remote reported min interarrival jitter : "
+ + minRemoteInterArrivalJitter + "\n" +
+ "remote reported max interarrival jitter : "
+ + maxRemoteInterArrivalJitter + "\n" +
+ "local collisions: " + s.getLocalColls() + "\n" +
+ "remote collisions: " + s.getRemoteColls() + "\n" +
+ "RTCP sent: " + s.getRTCPSent() + "\n" +
+
+ "transmit failed: " + s.getTransmitFailed()
+ );
+
+ GlobalReceptionStats rs = rtpManager.getGlobalReceptionStats();
+
+ logger.trace(
+ "global reception stats (" + rtpManagerDescription + "): \n" +
+ "packets received: " + rs.getPacketsRecd() + "\n" +
+ "bytes received: " + rs.getBytesRecd() + "\n" +
+ "packets lost: " + statisticsEngine.getLost() + "\n" +
+ "min interarrival jitter : "
+ + statisticsEngine.getMinInterArrivalJitter() + "\n" +
+ "max interarrival jitter : "
+ + statisticsEngine.getMaxInterArrivalJitter() + "\n" +
+ "RTCPs received: " + rs.getRTCPRecd() + "\n" +
+ "bad RTCP packets: " + rs.getBadRTCPPkts() + "\n" +
+ "bad RTP packets: " + rs.getBadRTPkts() + "\n" +
+ "local collisions: " + rs.getLocalColls() + "\n" +
+ "malformed BYEs: " + rs.getMalformedBye() + "\n" +
+ "malformed RRs: " + rs.getMalformedRR() + "\n" +
+ "malformed SDESs: " + rs.getMalformedSDES() + "\n" +
+ "malformed SRs: " + rs.getMalformedSR() + "\n" +
+ "packets looped: " + rs.getPacketsLooped() + "\n" +
+ "remote collisions: " + rs.getRemoteColls() + "\n" +
+ "SRRs received: " + rs.getSRRecd() + "\n" +
+ "transmit failed: " + rs.getTransmitFailed() + "\n" +
+ "unknown types: " + rs.getUnknownTypes()
+ );
+ }
+ catch(Throwable t)
+ {
+ logger.error("Error writing statistics", t);
+ }
}
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/transform/rtcp/StatisticsEngine.java b/src/net/java/sip/communicator/impl/neomedia/transform/rtcp/StatisticsEngine.java
new file mode 100644
index 0000000..debf37b
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/neomedia/transform/rtcp/StatisticsEngine.java
@@ -0,0 +1,183 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.neomedia.transform.rtcp;
+
+import com.sun.media.rtp.*;
+import net.java.sip.communicator.impl.neomedia.*;
+import net.java.sip.communicator.impl.neomedia.transform.*;
+
+import net.java.sip.communicator.util.*;
+import net.sf.fmj.media.rtp.*;
+
+/**
+ * @author Damian Minkov
+ */
+public class StatisticsEngine
+ implements TransformEngine,
+ PacketTransformer
+{
+ /**
+ * The <tt>Logger</tt> used by the <tt>StatisticsEngine</tt> class
+ * and its instances for logging output.
+ */
+ private static final Logger logger
+ = Logger.getLogger(StatisticsEngine.class);
+
+ /**
+ * Number of sender reports send.
+ * Used only for logging and debug purposes.
+ */
+ private long numberOfSenderReports = 0;
+
+ /**
+ * The minimum inter arrival jitter value we have reported.
+ */
+ private long maxInterArrivalJitter = 0;
+
+ /**
+ * The minimum inter arrival jitter value we have reported.
+ */
+ private long minInterArrivalJitter = -1;
+
+ /**
+ * Number of lost packets reported.
+ */
+ private long lost = 0;
+
+ /**
+ * Finds the info needed for statistics in the packet and stores it.
+ * Then returns the same packet as we are not modifying it.
+ *
+ * @param pkt the packet
+ * @return the packet
+ */
+ public RawPacket transform(RawPacket pkt)
+ {
+ if(!logger.isTraceEnabled())
+ return pkt;
+
+ try
+ {
+ numberOfSenderReports++;
+
+ byte[] data = pkt.getBuffer();
+ int offset = pkt.getOffset();
+ int length = pkt.getLength();
+
+ RTCPHeader header = new RTCPHeader(
+ data, offset, length);
+ if (header.getPacketType() == RTCPPacket.SR)
+ {
+ RTCPSenderReport report = new RTCPSenderReport(
+ data, offset, length);
+
+ if(report.getFeedbackReports().size() > 0)
+ {
+ RTCPFeedback feedback =
+ (RTCPFeedback)report.getFeedbackReports().get(0);
+
+ long jitter = feedback.getJitter();
+
+ if(jitter < getMinInterArrivalJitter()
+ || getMinInterArrivalJitter() == -1)
+ minInterArrivalJitter = jitter;
+
+ if(getMaxInterArrivalJitter() < jitter)
+ maxInterArrivalJitter = jitter;
+
+ lost = feedback.getNumLost();
+
+ // As sender reports are send on every 5 seconds
+ // print every 4th packet, on every 20 seconds
+ if(numberOfSenderReports%4 != 1)
+ return pkt;
+
+ StringBuilder buff = new StringBuilder(
+ "Sending report to remote party [packetCount:");
+
+ buff.append(report.getSenderPacketCount())
+ .append(", bytes:").append(report.getSenderByteCount())
+ .append(", interarrival jitter:")
+ .append(jitter)
+ .append(", lost:").append(feedback.getNumLost())
+ .append(", lastSRBefore:")
+ .append((int) (feedback.getDLSR() / 65.536))
+ .append("ms ]");
+ logger.trace(buff.toString());
+ }
+ }
+ }
+ catch(Throwable t)
+ {
+ t.printStackTrace();
+ }
+
+ return pkt;
+ }
+
+ /**
+ * Returns the packet as we are listening just for sending packages.
+ *
+ * @param pkt the packet without any change.
+ * @return the packet without any change.
+ */
+ public RawPacket reverseTransform(RawPacket pkt)
+ {
+ return pkt;
+ }
+
+ /**
+ * Always returns <tt>null</tt> since this engine does not require any
+ * RTP transformations.
+ *
+ * @return <tt>null</tt> since this engine does not require any
+ * RTP transformations.
+ */
+ public PacketTransformer getRTPTransformer()
+ {
+ return null;
+ }
+
+ /**
+ * Returns a reference to this class since it is performing RTP
+ * transformations in here.
+ *
+ * @return a reference to <tt>this</tt> instance of the
+ * <tt>StatisticsEngine</tt>.
+ */
+ public PacketTransformer getRTCPTransformer()
+ {
+ return this;
+ }
+
+ /**
+ * The minimum inter arrival jitter value we have reported.
+ * @return minimum inter arrival jitter value we have reported.
+ */
+ public long getMaxInterArrivalJitter()
+ {
+ return maxInterArrivalJitter;
+ }
+
+ /**
+ * The maximum inter arrival jitter value we have reported.
+ * @return maximum inter arrival jitter value we have reported.
+ */
+ public long getMinInterArrivalJitter()
+ {
+ return minInterArrivalJitter;
+ }
+
+ /**
+ * Number of lost packets reported.
+ * @return number of lost packets reported.
+ */
+ public long getLost()
+ {
+ return lost;
+ }
+}