예제 #1
0
  /**
   * 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;
  }
예제 #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;
      }
예제 #3
0
  /**
   * 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);
  }
예제 #4
0
 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);
         }
       }
     }
   }
 }
예제 #5
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 */);
  }
예제 #6
0
  /**
   * 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;
  }
예제 #7
0
            @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;
            }
예제 #8
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;
      }
예제 #9
0
 /**
  * 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;
 }