diff options
author | Damian Minkov <damencho@jitsi.org> | 2010-12-16 07:34:31 +0000 |
---|---|---|
committer | Damian Minkov <damencho@jitsi.org> | 2010-12-16 07:34:31 +0000 |
commit | 2a29e3645e1729aa668892df5732f1463a60835d (patch) | |
tree | c771a95eda989d87aaa5e09470a63fe0b120c706 /src/net | |
parent | 8a23901ba4e2554f11fc47c8ad3500e92e5e773f (diff) | |
download | jitsi-2a29e3645e1729aa668892df5732f1463a60835d.zip jitsi-2a29e3645e1729aa668892df5732f1463a60835d.tar.gz jitsi-2a29e3645e1729aa668892df5732f1463a60835d.tar.bz2 |
Update media statistics.
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java | 170 | ||||
-rw-r--r-- | src/net/java/sip/communicator/impl/neomedia/transform/rtcp/StatisticsEngine.java | 183 |
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; + } +} |