/** * Retransmits a packet to {@link #channel}. If the destination supports the RTX format, the * packet will be encapsulated in RTX, otherwise, the packet will be retransmitted as-is. * * @param pkt the packet to retransmit. * @param after the {@code TransformEngine} in the chain of {@code TransformEngine}s of the * associated {@code MediaStream} after which the injection of {@code pkt} is to begin * @return {@code true} if the packet was successfully retransmitted, {@code false} otherwise. */ public boolean retransmit(RawPacket pkt, TransformEngine after) { boolean destinationSupportsRtx = channel.getRtxPayloadType() != -1; boolean retransmitPlain; if (destinationSupportsRtx) { long rtxSsrc = getPairedSsrc(pkt.getSSRC()); if (rtxSsrc == -1) { logger.warn("Cannot find SSRC for RTX, retransmitting plain."); retransmitPlain = true; } else { retransmitPlain = !encapsulateInRtxAndTransmit(pkt, rtxSsrc); } } else { retransmitPlain = true; } if (retransmitPlain) { MediaStream mediaStream = channel.getStream(); if (mediaStream != null) { try { mediaStream.injectPacket(pkt, /* data */ true, after); } catch (TransmissionFailedException tfe) { logger.warn("Failed to retransmit a packet."); return false; } } } return true; }
/** Implements {@link PacketTransformer#transform(RawPacket[])}. {@inheritDoc} */ @Override public RawPacket transform(RawPacket pkt) { byte rtxPt; if (pkt != null && (rtxPt = channel.getRtxPayloadType()) != -1 && pkt.getPayloadType() == rtxPt) { pkt = handleRtxPacket(pkt); } return pkt; }
/** * Handles an RTX packet and returns it. * * @param pkt the packet to handle. * @return the packet */ private RawPacket handleRtxPacket(RawPacket pkt) { boolean destinationSupportsRtx = channel.getRtxPayloadType() != -1; RawPacket mediaPacket = createMediaPacket(pkt); if (mediaPacket != null) { RawPacketCache cache = channel.getStream().getPacketCache(); if (cache != null) { cache.cachePacket(mediaPacket); } } if (destinationSupportsRtx) { pkt.setSequenceNumber( getNextRtxSequenceNumber(pkt.getSSRC() & 0xffffffffL, pkt.getSequenceNumber())); } else { // If the media packet was not reconstructed, drop the RTX packet // (by returning null). return mediaPacket; } return pkt; }