/** * Updates the participant with information for receiver reports. * * @param packetLength to keep track of received octets * @param pkt the most recently received packet */ protected void updateRRStats(int packetLength, RtpPkt pkt) { int curSeqNum = pkt.getSeqNumber(); if (firstSeqNumber < 0) { firstSeqNumber = curSeqNum; } receivedOctets += packetLength; receivedSinceLastSR++; receivedPkts++; long curTime = System.currentTimeMillis(); if (this.lastSeqNumber < curSeqNum) { // In-line packet, best thing you could hope for this.lastSeqNumber = curSeqNum; } else if (this.lastSeqNumber - this.lastSeqNumber < -100) { // Sequence counter rolled over this.lastSeqNumber = curSeqNum; seqRollOverCount++; } else { // This was probably a duplicate or a late arrival. } // Calculate jitter if (this.lastRtpPkt > 0) { long D = (pkt.getTimeStamp() - curTime) - (this.lastRtpTimestamp - this.lastRtpPkt); if (D < 0) D = (-1) * D; this.interArrivalJitter += ((double) D - this.interArrivalJitter) / 16.0; } lastRtpPkt = curTime; lastRtpTimestamp = pkt.getTimeStamp(); }
/** * Send data to all participants registered as receivers, using the current timeStamp and payload * type. The RTP timestamp will be the same for all the packets. * * @param buffers A buffer of bytes, should not bed padded and less than 1500 bytes on most * networks. * @param csrcArray an array with the SSRCs of contributing sources * @param markers An array indicating what packets should be marked. Rarely anything but the first * one * @param rtpTimestamp The RTP timestamp to be applied to all packets * @param seqNumbers An array with the sequence number associated with each byte[] * @return null if there was a problem sending the packets, 2-dim array with {RTP Timestamp, * Sequence number} */ public long[][] sendData( byte[][] buffers, long[] csrcArray, boolean[] markers, long rtpTimestamp, long[] seqNumbers) { logger.debug("-> RTPSession.sendData(byte[])"); // Same RTP timestamp for all if (rtpTimestamp < 0) rtpTimestamp = System.currentTimeMillis(); // Return values long[][] ret = new long[buffers.length][2]; for (int i = 0; i < buffers.length; i++) { byte[] buf = buffers[i]; boolean marker = false; if (markers != null) marker = markers[i]; if (buf.length > 1500) { System.out.println( "RTPSession.sendData() called with buffer exceeding 1500 bytes (" + buf.length + ")"); } // Get the return values ret[i][0] = rtpTimestamp; if (seqNumbers == null) { ret[i][1] = getNextSeqNum(); } else { ret[i][1] = seqNumbers[i]; } // Create a new RTP Packet RtpPkt pkt = new RtpPkt(rtpTimestamp, this.ssrc, (int) ret[i][1], this.payloadType, buf); if (csrcArray != null) pkt.setCsrcs(csrcArray); pkt.setMarked(marker); // Creates a raw packet byte[] pktBytes = pkt.encode(); // System.out.println(Integer.toString(StaticProcs.bytesToUIntInt(pktBytes, 2))); // Pre-flight check, are resolving an SSRC conflict? if (this.conflict) { System.out.println("RTPSession.sendData() called while trying to resolve conflict."); return null; } if (this.mcSession) { DatagramPacket packet = null; try { packet = new DatagramPacket(pktBytes, pktBytes.length, this.mcGroup, this.rtpMCSock.getPort()); } catch (Exception e) { System.out.println("RTPSession.sendData() packet creation failed."); e.printStackTrace(); return null; } try { rtpMCSock.send(packet); // Debug if (this.debugAppIntf != null) { this.debugAppIntf.packetSent( 1, (InetSocketAddress) packet.getSocketAddress(), new String( "Sent multicast RTP packet of size " + packet.getLength() + " to " + packet.getSocketAddress().toString() + " via " + rtpMCSock.getLocalSocketAddress().toString())); } } catch (Exception e) { System.out.println("RTPSession.sendData() multicast failed."); e.printStackTrace(); return null; } } else { // Loop over recipients Iterator<Participant> iter = partDb.getUnicastReceivers(); while (iter.hasNext()) { InetSocketAddress receiver = iter.next().rtpAddress; DatagramPacket packet = null; logger.debug(" Sending to {}", receiver); try { packet = new DatagramPacket(pktBytes, pktBytes.length, receiver); } catch (Exception e) { System.out.println("RTPSession.sendData() packet creation failed."); e.printStackTrace(); return null; } // Actually send the packet try { rtpSock.send(packet); // Debug if (this.debugAppIntf != null) { this.debugAppIntf.packetSent( 0, (InetSocketAddress) packet.getSocketAddress(), new String( "Sent unicast RTP packet of size " + packet.getLength() + " to " + packet.getSocketAddress().toString() + " via " + rtpSock.getLocalSocketAddress().toString())); } } catch (Exception e) { System.out.println("RTPSession.sendData() unicast failed."); e.printStackTrace(); return null; } } } // Update our stats this.sentPktCount++; this.sentOctetCount++; logger.info("<- RTPSession.sendData(byte[])", pkt.getSeqNumber()); } return ret; }