/** push bytes back, to be read again later. */
 private void pushback(byte[] bytes, int len) {
   if (pushbackBufferLen == 0) {
     pushbackBuffer = bytes; // TODO: copy?
     pushbackBufferLen = len;
     pushbackBufferOffset = 0;
   } else {
     final byte[] newPushbackBuffer = new byte[pushbackBufferLen + len];
     System.arraycopy(pushbackBuffer, 0, newPushbackBuffer, 0, pushbackBufferLen);
     System.arraycopy(bytes, 0, newPushbackBuffer, pushbackBufferLen, len);
     pushbackBuffer = newPushbackBuffer;
     pushbackBufferLen = pushbackBufferLen + len;
     pushbackBufferOffset = 0;
   }
 }
예제 #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;
      }
 /** supports pushback. */
 private int read(byte[] buffer, int offset, int length) throws IOException {
   if (pushbackBufferLen > 0) { // read from pushback buffer
     final int lenToCopy = length < pushbackBufferLen ? length : pushbackBufferLen;
     System.arraycopy(pushbackBuffer, pushbackBufferOffset, buffer, offset, lenToCopy);
     pushbackBufferLen -= lenToCopy;
     pushbackBufferOffset += lenToCopy;
     return lenToCopy;
   } else {
     return stream.read(buffer, offset, length);
   }
 }
예제 #4
0
  public synchronized void setPacketSize(int newPacketSize) {
    packetSize = newPacketSize;

    sample_count = packetSize;

    if (history == null) {
      history = new byte[packetSize];
      return;
    }

    if (packetSize > history.length) {
      byte[] newHistory = new byte[packetSize];
      System.arraycopy(history, 0, newHistory, 0, historyLength);
      history = newHistory;
    }
  }
예제 #5
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;
      }
예제 #6
0
  /** {@inheritDoc} */
  @Override
  protected int doProcess(Buffer inBuffer, Buffer outBuffer) {
    byte[] inData = (byte[]) inBuffer.getData();
    int inOffset = inBuffer.getOffset();

    if (!VP8PayloadDescriptor.isValid(inData, inOffset)) {
      logger.warn("Invalid RTP/VP8 packet discarded.");
      outBuffer.setDiscard(true);
      return BUFFER_PROCESSED_FAILED; // XXX: FAILED or OK?
    }

    long inSeq = inBuffer.getSequenceNumber();
    long inRtpTimestamp = inBuffer.getRtpTimeStamp();
    int inPictureId = VP8PayloadDescriptor.getPictureId(inData, inOffset);
    boolean inMarker = (inBuffer.getFlags() & Buffer.FLAG_RTP_MARKER) != 0;
    boolean inIsStartOfFrame = VP8PayloadDescriptor.isStartOfFrame(inData, inOffset);
    int inLength = inBuffer.getLength();
    int inPdSize = VP8PayloadDescriptor.getSize(inData, inOffset);
    int inPayloadLength = inLength - inPdSize;

    if (empty && lastSentSeq != -1 && seqNumComparator.compare(inSeq, lastSentSeq) != 1) {
      if (logger.isInfoEnabled()) logger.info("Discarding old packet (while empty) " + inSeq);
      outBuffer.setDiscard(true);
      return BUFFER_PROCESSED_OK;
    }

    if (!empty) {
      // if the incoming packet has a different PictureID or timestamp
      // than those of the current frame, then it belongs to a different
      // frame.
      if ((inPictureId != -1 && pictureId != -1 && inPictureId != pictureId)
          | (timestamp != -1 && inRtpTimestamp != -1 && inRtpTimestamp != timestamp)) {
        if (seqNumComparator.compare(inSeq, firstSeq) != 1) // inSeq <= firstSeq
        {
          // the packet belongs to a previous frame. discard it
          if (logger.isInfoEnabled()) logger.info("Discarding old packet " + inSeq);
          outBuffer.setDiscard(true);
          return BUFFER_PROCESSED_OK;
        } else // inSeq > firstSeq (and also presumably isSeq > lastSeq)
        {
          // the packet belongs to a subsequent frame (to the one
          // currently being held). Drop the current frame.

          if (logger.isInfoEnabled())
            logger.info(
                "Discarding saved packets on arrival of"
                    + " a packet for a subsequent frame: "
                    + inSeq);

          // TODO: this would be the place to complain about the
          // not-well-received PictureID by sending a RTCP SLI or NACK.
          reinit();
        }
      }
    }

    // a whole frame in a single packet. avoid the extra copy to
    // this.data and output it immediately.
    if (empty && inMarker && inIsStartOfFrame) {
      byte[] outData = validateByteArraySize(outBuffer, inPayloadLength, false);
      System.arraycopy(inData, inOffset + inPdSize, outData, 0, inPayloadLength);
      outBuffer.setOffset(0);
      outBuffer.setLength(inPayloadLength);
      outBuffer.setRtpTimeStamp(inBuffer.getRtpTimeStamp());

      if (TRACE) logger.trace("Out PictureID=" + inPictureId);

      lastSentSeq = inSeq;

      return BUFFER_PROCESSED_OK;
    }

    // add to this.data
    Container container = free.poll();
    if (container == null) container = new Container();
    if (container.buf == null || container.buf.length < inPayloadLength)
      container.buf = new byte[inPayloadLength];

    if (data.get(inSeq) != null) {
      if (logger.isInfoEnabled())
        logger.info("(Probable) duplicate packet detected, discarding " + inSeq);
      outBuffer.setDiscard(true);
      return BUFFER_PROCESSED_OK;
    }

    System.arraycopy(inData, inOffset + inPdSize, container.buf, 0, inPayloadLength);
    container.len = inPayloadLength;
    data.put(inSeq, container);

    // update fields
    frameLength += inPayloadLength;
    if (firstSeq == -1 || (seqNumComparator.compare(firstSeq, inSeq) == 1)) firstSeq = inSeq;
    if (lastSeq == -1 || (seqNumComparator.compare(inSeq, lastSeq) == 1)) lastSeq = inSeq;

    if (empty) {
      // the first received packet for the current frame was just added
      empty = false;
      timestamp = inRtpTimestamp;
      pictureId = inPictureId;
    }

    if (inMarker) haveEnd = true;
    if (inIsStartOfFrame) haveStart = true;

    // check if we have a full frame
    if (frameComplete()) {
      byte[] outData = validateByteArraySize(outBuffer, frameLength, false);
      int ptr = 0;
      Container b;
      for (Map.Entry<Long, Container> entry : data.entrySet()) {
        b = entry.getValue();
        System.arraycopy(b.buf, 0, outData, ptr, b.len);
        ptr += b.len;
      }

      outBuffer.setOffset(0);
      outBuffer.setLength(frameLength);
      outBuffer.setRtpTimeStamp(inBuffer.getRtpTimeStamp());

      if (TRACE) logger.trace("Out PictureID=" + inPictureId);
      lastSentSeq = lastSeq;

      // prepare for the next frame
      reinit();

      return BUFFER_PROCESSED_OK;
    } else {
      // frame not complete yet
      outBuffer.setDiscard(true);
      return OUTPUT_BUFFER_NOT_FILLED;
    }
  }
  public int process(Buffer inputBuffer, Buffer outputBuffer) {

    if (pendingFrames > 0) {
      // System.out.println("packetizing");
      return BUFFER_PROCESSED_OK;
    }

    if (!checkInputBuffer(inputBuffer)) {
      return BUFFER_PROCESSED_FAILED;
    }

    if (isEOM(inputBuffer)) {
      propagateEOM(outputBuffer);
      return BUFFER_PROCESSED_OK;
    }

    int inpOffset = inputBuffer.getOffset();
    int inpLength = inputBuffer.getLength();
    int outLength = 0;
    int outOffset = 0;
    byte[] inpData = (byte[]) inputBuffer.getData();
    byte[] outData =
        validateByteArraySize(outputBuffer, calculateOutputSize(inpData.length + historySize));
    int historyLength = history.getLength();
    byte[] historyData = validateByteArraySize(history, historySize);
    int framesNumber = calculateFramesNumber(inpData.length + historySize);

    if ((regions == null) || (regions.length < framesNumber + 1))
      regions = new int[framesNumber + 1];

    if ((regionsTypes == null) || (regionsTypes.length < framesNumber))
      regionsTypes = new int[framesNumber];

    if (historyLength != 0) {
      int bytesToCopy = (historyData.length - historyLength);
      if (bytesToCopy > inpLength) {
        bytesToCopy = inpLength;
      }

      System.arraycopy(inpData, inpOffset, historyData, historyLength, bytesToCopy);

      codecProcess(
          historyData,
          0,
          outData,
          outOffset,
          historyLength + bytesToCopy,
          readBytes,
          writeBytes,
          frameNumber,
          regions,
          regionsTypes);

      if (readBytes[0] <= 0) {
        if (writeBytes[0] <= 0) {
          // System.err.println("Returning output buffer not filled");
          return OUTPUT_BUFFER_NOT_FILLED;
        } else {
          updateOutput(outputBuffer, outputFormat, writeBytes[0], 0);
          // System.err.println("Returning OK");
          return BUFFER_PROCESSED_OK;
        }
      }

      // System.out.println("1: "+inpLength+" "+readBytes[0]+" "+writeBytes[0]);

      outOffset += writeBytes[0];
      outLength += writeBytes[0];

      inpOffset += (readBytes[0] - historyLength);
      inpLength += (historyLength - readBytes[0]);
    }

    codecProcess(
        inpData,
        inpOffset,
        outData,
        outOffset,
        inpLength,
        readBytes,
        writeBytes,
        frameNumber,
        regions,
        regionsTypes);
    // System.out.println("2: "+inpLength+" "+readBytes[0]+" "+writeBytes[0]);

    // debug
    // for (int i=0; i<frameNumber[0];i++ ) {
    // System.out.println(i+" "+regions[i]+" - "+regions[i+1]+" type "+regionsTypes[i]);
    // }

    outLength += writeBytes[0];

    inpOffset += readBytes[0];
    inpLength -= readBytes[0];

    System.arraycopy(inpData, inpOffset, historyData, 0, inpLength);
    history.setLength(inpLength);

    updateOutput(outputBuffer, outputFormat, outLength, 0);

    return BUFFER_PROCESSED_OK;
  }