/** * Return a set of all items with type CNAME from the RTCP SDES packet <tt>pkt</tt>. * * @param pkt the packet to parse for CNAME items. * @retur a set of all items with type CNAME from the RTCP SDES packet <tt>pkt</tt>. */ private Set<CNAMEItem> getCnameItems(RawPacket pkt) { Set<CNAMEItem> ret = new HashSet<CNAMEItem>(); byte[] buf = pkt.getBuffer(); int off = pkt.getOffset(); int len = pkt.getLength(); // first item int ptr = 4; while (ptr + 6 < len) // an item is at least 6B: 4B ssrc, 1B type, 1B len { int type = buf[off + ptr + 4]; int len2 = buf[off + ptr + 5]; if (ptr + 6 + len2 >= len) // not enough buffer for the whole item break; if (type == 1) // CNAME { CNAMEItem item = new CNAMEItem(); item.ssrc = readUnsignedIntAsLong(buf, off + ptr); item.cname = readString(buf, off + ptr + 6, len2); ret.add(item); } ptr += 6 + len2; } return ret; }
public int write(byte[] buffer, int offset, int length, boolean transform) { RawPacket pkt = rawPacketArray[0]; if (pkt == null) pkt = new RawPacket(); rawPacketArray[0] = pkt; byte[] pktBuf = pkt.getBuffer(); if (pktBuf == null || pktBuf.length < length) { pktBuf = new byte[length]; pkt.setBuffer(pktBuf); } System.arraycopy(buffer, offset, pktBuf, 0, length); pkt.setOffset(0); pkt.setLength(length); if (transform) { PacketTransformer packetTransformer = isControlStream ? rtcpPacketTransformer : rtpPacketTransformer; if (packetTransformer != null) rawPacketArray = packetTransformer.reverseTransform(rawPacketArray); } SourceTransferHandler transferHandler; PushSourceStream pushSourceStream; try { if (isControlStream) { transferHandler = controlTransferHandler; pushSourceStream = getControlInputStream(); } else { transferHandler = dataTransferHandler; pushSourceStream = getDataInputStream(); } } catch (IOException ioe) { throw new UndeclaredThrowableException(ioe); } for (int i = 0; i < rawPacketArray.length; i++) { RawPacket packet = rawPacketArray[i]; // keep the first element for reuse if (i != 0) rawPacketArray[i] = null; if (packet != null) { if (isControlStream) pendingControlPacket = packet; else pendingDataPacket = packet; if (transferHandler != null) { transferHandler.transferData(pushSourceStream); } } } return length; }
/** * Handles an RTCP Sender Report packet. * * @param pkt the packet to handle. * @param localTime the local time of reception of the packet. */ private void addSR(RawPacket pkt, long localTime) { long ssrc = pkt.getRTCPSSRC() & 0xffffffffL; long rtpTime = pkt.readUnsignedIntAsLong(16); long sec = pkt.readUnsignedIntAsLong(8); long fract = pkt.readUnsignedIntAsLong(12); double ntpTime = sec + (((double) fract) / (1L << 32)); if (localTime != -1 && ntpTime != -1.0) mapLocalToNtp(ssrc, localTime, ntpTime); if (rtpTime != -1 && ntpTime != -1.0) mapRtpToNtp(ssrc, rtpTime, ntpTime); }
private void handleRtpPacket(RawPacket pkt) { if (pkt != null && pkt.getPayloadType() == vp8PayloadType) { int ssrc = pkt.getSSRC(); if (!activeVideoSsrcs.contains(ssrc & 0xffffffffL)) { synchronized (activeVideoSsrcs) { if (!activeVideoSsrcs.contains(ssrc & 0xffffffffL)) { activeVideoSsrcs.add(ssrc & 0xffffffffL); rtcpFeedbackSender.sendFIR(ssrc); } } } } }
private void emptyPacketBuffer(long ssrc) { RawPacket[] pkts = rtpConnector.packetBuffer.emptyBuffer(ssrc); RTPConnectorImpl.OutputDataStreamImpl dataStream; try { dataStream = rtpConnector.getDataOutputStream(); } catch (IOException ioe) { logger.error("Failed to empty packet buffer for SSRC=" + ssrc + ": " + ioe); return; } for (RawPacket pkt : pkts) dataStream.write( pkt.getBuffer(), pkt.getOffset(), pkt.getLength(), false /* already transformed */); }
/** * Checks whether <tt>pkt</tt> looks like a valid RTCP packet. * * @param pkt the packet to check. * @return <tt>true</tt> if <tt>pkt</tt> seems to be a valid RTCP packet. */ private boolean isValidRTCP(RawPacket pkt) { byte[] buf = pkt.getBuffer(); int off = pkt.getOffset(); int len = pkt.getLength(); if (len < 4) return false; int v = (buf[off] & 0xc0) >>> 6; if (v != 2) return false; int lengthInWords = (buf[off + 2] & 0xFF) << 8 | (buf[off + 3] & 0xFF); int lengthInBytes = (lengthInWords + 1) * 4; if (len < lengthInBytes) return false; return true; }
@Override public RawPacket reverseTransform(RawPacket pkt) { RecorderRtpImpl.this.handleRtcpPacket(pkt); if (pkt != null && pkt.getRTCPPayloadType() == 203) { // An RTCP BYE packet. Remove the receive stream before // it gets to FMJ, because we want to, for example, // flush the packet buffer before that. long ssrc = pkt.getRTCPSSRC() & 0xffffffffl; if (logger.isInfoEnabled()) logger.info("RTCP BYE for SSRC=" + ssrc); ReceiveStreamDesc receiveStream = findReceiveStream(ssrc); if (receiveStream != null) removeReceiveStream(receiveStream, false); } return pkt; }
@Override public int read(byte[] buffer, int offset, int length) throws IOException { RawPacket pendingPacket; if (isControlStream) { pendingPacket = pendingControlPacket; } else { pendingPacket = pendingDataPacket; } int bytesToRead = 0; byte[] pendingPacketBuffer = pendingPacket.getBuffer(); if (pendingPacketBuffer != null) { int pendingPacketLength = pendingPacket.getLength(); bytesToRead = length > pendingPacketLength ? pendingPacketLength : length; System.arraycopy( pendingPacketBuffer, pendingPacket.getOffset(), buffer, offset, bytesToRead); } return bytesToRead; }
/** * Returns the value of the packet type field from the RTCP header of <tt>pkt</tt>. Assumes that * <tt>pkt</tt> is a valid RTCP packet (at least as reported by {@link #isValidRTCP(RawPacket)}). * * @param pkt the packet to get the packet type of. * @return the value of the packet type field from the RTCP header of <tt>pkt</tt>. */ private int getPacketType(RawPacket pkt) { return pkt.getBuffer()[pkt.getOffset() + 1] & 0xff; }