Example #1
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;
      }
  /**
   * 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;
  }
  /**
   * Creates a {@code RawPacket} which represents the original packet encapsulated in {@code pkt}
   * using the RTX format.
   *
   * @param pkt the packet from which to extract a media packet.
   * @return the extracted media packet.
   */
  private RawPacket createMediaPacket(RawPacket pkt) {
    RawPacket mediaPacket = null;
    long rtxSsrc = pkt.getSSRC() & 0xffffffffL;

    // We need to know the SSRC paired with rtxSsrc *as seen by the
    // receiver (i.e. this.channel)*. However, we only store SSRCs
    // that endpoints *send* with.
    // We therefore assume that SSRC re-writing has not introduced any
    // new SSRCs and therefor the FID mappings known to the senders
    // also apply to receivers.
    RtpChannel sourceChannel = channel.getContent().findChannelByFidSsrc(rtxSsrc);
    if (sourceChannel != null) {
      long mediaSsrc = sourceChannel.getFidPairedSsrc(rtxSsrc);
      if (mediaSsrc != -1) {
        byte apt = sourceChannel.getRtxAssociatedPayloadType();
        if (apt != -1) {
          mediaPacket = new RawPacket(pkt.getBuffer().clone(), pkt.getOffset(), pkt.getLength());

          // Remove the RTX header by moving the RTP header two bytes
          // right.
          byte[] buf = mediaPacket.getBuffer();
          int off = mediaPacket.getOffset();
          System.arraycopy(buf, off, buf, off + 2, mediaPacket.getHeaderLength());

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

          mediaPacket.setSSRC((int) mediaSsrc);
          mediaPacket.setSequenceNumber(pkt.getOriginalSequenceNumber());
          mediaPacket.setPayloadType(apt);
        }
      }
    }

    return mediaPacket;
  }