コード例 #1
0
ファイル: XRTMPDecoder.java プロジェクト: gillbates/rtmplite
  /**
   * Decodes packet header.
   *
   * @param in Input IoBuffer
   * @param lastHeader Previous header
   * @return Decoded header
   */
  public static Header decodeHeader(IoBuffer in, Header lastHeader) {
    if (log.isTraceEnabled()) {
      log.trace("decodeHeader - lastHeader: {} buffer: {}", lastHeader, in);
    }
    byte headerByte = in.get();
    int headerValue;
    int byteCount = 1;
    if ((headerByte & 0x3f) == 0) {
      // Two byte header
      headerValue = (headerByte & 0xff) << 8 | (in.get() & 0xff);
      byteCount = 2;
    } else if ((headerByte & 0x3f) == 1) {
      // Three byte header
      headerValue = (headerByte & 0xff) << 16 | (in.get() & 0xff) << 8 | (in.get() & 0xff);
      byteCount = 3;
    } else {
      // Single byte header
      headerValue = headerByte & 0xff;
      byteCount = 1;
    }
    final int channelId = RTMPUtils.decodeChannelId(headerValue, byteCount);
    final int headerSize = RTMPUtils.decodeHeaderSize(headerValue, byteCount);
    Header header = new Header();
    header.setChannelId(channelId);
    if (headerSize != HEADER_NEW && lastHeader == null) {
      log.error("Last header null not new, headerSize: {}, channelId {}", headerSize, channelId);
      // this will trigger an error status, which in turn will disconnect the "offending" flash
      // player
      // preventing a memory leak and bringing the whole server to its knees
      return null;
    }
    int timeValue;
    switch (headerSize) {
      case HEADER_NEW:
        // an absolute time value
        timeValue = RTMPUtils.readUnsignedMediumInt(in);
        header.setSize(RTMPUtils.readUnsignedMediumInt(in));
        header.setDataType(in.get());
        header.setStreamId(RTMPUtils.readReverseInt(in));
        if (timeValue == 0xffffff) {
          timeValue = (int) (in.getUnsignedInt() & Integer.MAX_VALUE);
          header.setExtendedTimestamp(timeValue);
        }
        header.setTimerBase(timeValue);
        header.setTimerDelta(0);
        break;
      case HEADER_SAME_SOURCE:
        // a delta time value
        timeValue = RTMPUtils.readUnsignedMediumInt(in);
        header.setSize(RTMPUtils.readUnsignedMediumInt(in));
        header.setDataType(in.get());
        header.setStreamId(lastHeader.getStreamId());
        if (timeValue == 0xffffff) {
          timeValue = (int) (in.getUnsignedInt() & Integer.MAX_VALUE);
          header.setExtendedTimestamp(timeValue);
        } else if (timeValue == 0 && header.getDataType() == TYPE_AUDIO_DATA) {
          // header.setIsGarbage(true);
          log.trace(
              "Audio with zero delta; setting to garbage; ChannelId: {}; DataType: {}; HeaderSize: {}",
              new Object[] {header.getChannelId(), header.getDataType(), headerSize});
        }
        header.setTimerBase(lastHeader.getTimerBase());
        header.setTimerDelta(timeValue);
        break;
      case HEADER_TIMER_CHANGE:
        // a delta time value
        timeValue = RTMPUtils.readUnsignedMediumInt(in);
        header.setSize(lastHeader.getSize());
        header.setDataType(lastHeader.getDataType());
        header.setStreamId(lastHeader.getStreamId());
        if (timeValue == 0xffffff) {
          timeValue = (int) (in.getUnsignedInt() & Integer.MAX_VALUE);
          header.setExtendedTimestamp(timeValue);
        } else if (timeValue == 0 && header.getDataType() == TYPE_AUDIO_DATA) {
          // header.setIsGarbage(true);
          log.trace(
              "Audio with zero delta; setting to garbage; ChannelId: {}; DataType: {}; HeaderSize: {}",
              new Object[] {header.getChannelId(), header.getDataType(), headerSize});
        }
        header.setTimerBase(lastHeader.getTimerBase());
        header.setTimerDelta(timeValue);
        break;
      case HEADER_CONTINUE:
        header.setSize(lastHeader.getSize());
        header.setDataType(lastHeader.getDataType());
        header.setStreamId(lastHeader.getStreamId());
        header.setTimerBase(lastHeader.getTimerBase());
        header.setTimerDelta(lastHeader.getTimerDelta());
        if (lastHeader.getExtendedTimestamp() != 0) {
          timeValue = (int) (in.getUnsignedInt() & Integer.MAX_VALUE);
          header.setExtendedTimestamp(timeValue);
          log.trace("HEADER_CONTINUE with extended timestamp: {}", timeValue);
        }
        break;
      default:
        log.error("Unexpected header size: {}", headerSize);
        return null;
    }

    log.trace("CHUNK, D, {}, {}", header, headerSize);
    return header;
  }