/** * Updates this <tt>RTPStatsMap</tt> with information it gets from the <tt>RawPacket</tt>. * * @param pkt the <tt>RawPacket</tt> that is being transmitted. */ public void apply(RawPacket pkt) { int ssrc = pkt.getSSRC(); if (this.containsKey(ssrc)) { RTPStatsEntry oldRtpStatsEntry = this.get(ssrc); // Replace whatever was in there before. A feature of the two's // complement encoding (which is used by Java integers) is that // the bitwise results for add, subtract, and multiply are the // same if both inputs are interpreted as signed values or both // inputs are interpreted as unsigned values. (Other encodings // like one's complement and signed magnitude don't have this // properly.) this.put( ssrc, new RTPStatsEntry( ssrc, oldRtpStatsEntry.getBytesSent() + pkt.getLength() - pkt.getHeaderLength() - pkt.getPaddingSize(), oldRtpStatsEntry.getPacketsSent() + 1)); } else { // Add a new <tt>RTPStatsEntry</tt> in this map. this.put( ssrc, new RTPStatsEntry( ssrc, pkt.getLength() - pkt.getHeaderLength() - pkt.getPaddingSize(), 1)); } }
/** * Updates octet count and packet count in sender reports found in the * <tt>RTCPCompoundPacket</tt>. * * @param pkt * @return {@code true} if the specified {@code pkt} was modified; otherwise, {@code false} */ public boolean gateway(RTCPCompoundPacket pkt) { RTCPPacket[] pkts; boolean modified = false; if (pkt != null && (pkts = pkt.packets) != null && pkts.length != 0) { for (RTCPPacket p : pkts) { switch (p.type) { case RTCPPacket.SR: RTCPSRPacket sr = (RTCPSRPacket) p; int ssrc = sr.ssrc; RTPStatsEntry rtpStats = rtpStatsMap.get(ssrc); if (rtpStats != null) { // Mark the packet as modified and update the octet // and packet count using the information gathered // by rtpStatsMap. sr.octetcount = rtpStats.getBytesSent(); sr.packetcount = rtpStats.getPacketsSent(); modified = true; } break; } } } return modified; }
/** * Makes <tt>RTCPSRPacket</tt>s for all the RTP streams that we're sending. * * @return a <tt>List</tt> of <tt>RTCPSRPacket</tt> for all the RTP streams that we're sending. */ private Collection<RTCPSRPacket> makeRTCPSRPackets(long time) { Collection<RTCPSRPacket> srPackets = new ArrayList<RTCPSRPacket>(); for (RTPStatsEntry rtpStatsEntry : rtpStatsMap.values()) { int ssrc = rtpStatsEntry.getSsrc(); RemoteClock estimate = remoteClockEstimator.estimate(ssrc, time); if (estimate == null) { // We're not going to go far without an estimate.. continue; } RTCPSRPacket srPacket = new RTCPSRPacket(ssrc, MIN_RTCP_REPORTS_BLOCKS_ARRAY); // Set the NTP timestamp for this SR. long estimatedRemoteTime = estimate.getRemoteTime(); long secs = estimatedRemoteTime / 1000L; double fraction = (estimatedRemoteTime - secs * 1000L) / 1000D; srPacket.ntptimestamplsw = (int) (fraction * 4294967296D); srPacket.ntptimestampmsw = secs; // Set the RTP timestamp. srPacket.rtptimestamp = estimate.getRtpTimestamp(); // Fill-in packet and octet send count. srPacket.packetcount = rtpStatsEntry.getPacketsSent(); srPacket.octetcount = rtpStatsEntry.getBytesSent(); srPackets.add(srPacket); } return srPackets; }