/**
   * 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;
  }