/** {@inheritDoc} */
        @Override
        public RawPacket transform(RawPacket pkt) {
          if (pkt == null) {
            return pkt;
          }

          RTCPCompoundPacket inPacket;
          try {
            inPacket =
                (RTCPCompoundPacket)
                    parser.parse(pkt.getBuffer(), pkt.getOffset(), pkt.getLength());
          } catch (BadFormatException e) {
            logger.warn("Failed to terminate an RTCP packet. " + "Dropping packet.");
            return null;
          }

          // Update our RTCP stats map (timestamps). This operation is
          // read-only.
          remoteClockEstimator.apply(inPacket);

          cnameRegistry.update(inPacket);

          // Remove SRs and RRs from the RTCP packet.
          pkt = feedbackGateway.gateway(inPacket);

          return pkt;
        }
Esempio n. 2
0
      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;
      }
Esempio n. 3
0
  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 */);
  }
Esempio n. 4
0
      @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;
      }
  /**
   * Removes the RTX encapsulation from a packet.
   *
   * @param pkt the packet to remove the RTX encapsulation from.
   * @return the original media packet represented by {@code pkt}, or null if we couldn't
   *     reconstruct the original packet.
   */
  private RawPacket deRtx(RawPacket pkt) {
    boolean success = false;

    if (pkt.getPayloadLength() - pkt.getPaddingSize() < 2) {
      // We need at least 2 bytes to read the OSN field.
      if (logger.isDebugEnabled()) {
        logger.debug("Dropping an incoming RTX packet with padding only: " + pkt);
      }
      return null;
    }

    long mediaSsrc = getPrimarySsrc(pkt);
    if (mediaSsrc != -1) {
      if (rtxAssociatedPayloadType != -1) {
        int osn = pkt.getOriginalSequenceNumber();
        // Remove the RTX header by moving the RTP header two bytes
        // right.
        byte[] buf = pkt.getBuffer();
        int off = pkt.getOffset();
        System.arraycopy(buf, off, buf, off + 2, pkt.getHeaderLength());

        pkt.setOffset(off + 2);
        pkt.setLength(pkt.getLength() - 2);

        pkt.setSSRC((int) mediaSsrc);
        pkt.setSequenceNumber(osn);
        pkt.setPayloadType(rtxAssociatedPayloadType);
        success = true;
      } else {
        logger.warn(
            "RTX packet received, but no APT is defined. Packet "
                + "SSRC "
                + pkt.getSSRCAsLong()
                + ", associated media"
                + " SSRC "
                + mediaSsrc);
      }
    }

    // If we failed to handle the RTX packet, drop it.
    return success ? pkt : null;
  }
  /**
   * Encapsulates {@code pkt} in the RTX format, using {@code rtxSsrc} as its SSRC, and transmits it
   * to {@link #channel} by injecting it in the {@code MediaStream}.
   *
   * @param pkt the packet to transmit.
   * @param rtxSsrc the SSRC for the RTX stream.
   * @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.
   */
  private boolean encapsulateInRtxAndTransmit(RawPacket pkt, long rtxSsrc, TransformEngine after) {
    byte[] buf = pkt.getBuffer();
    int len = pkt.getLength();
    int off = pkt.getOffset();

    byte[] newBuf = new byte[len + 2];
    RawPacket rtxPkt = new RawPacket(newBuf, 0, len + 2);

    int osn = pkt.getSequenceNumber();
    int headerLength = pkt.getHeaderLength();
    int payloadLength = pkt.getPayloadLength();

    // Copy the header.
    System.arraycopy(buf, off, newBuf, 0, headerLength);

    // Set the OSN field.
    newBuf[headerLength] = (byte) ((osn >> 8) & 0xff);
    newBuf[headerLength + 1] = (byte) (osn & 0xff);

    // Copy the payload.
    System.arraycopy(buf, off + headerLength, newBuf, headerLength + 2, payloadLength);

    MediaStream mediaStream = channel.getStream();
    if (mediaStream != null) {
      rtxPkt.setSSRC((int) rtxSsrc);
      rtxPkt.setPayloadType(rtxPayloadType);
      // Only call getNextRtxSequenceNumber() when we're sure we're going
      // to transmit a packet, because it consumes a sequence number.
      rtxPkt.setSequenceNumber(getNextRtxSequenceNumber(rtxSsrc));
      try {
        mediaStream.injectPacket(rtxPkt, /* data */ true, after);
      } catch (TransmissionFailedException tfe) {
        logger.warn("Failed to transmit an RTX packet.");
        return false;
      }
    }

    return true;
  }