Package org.red5.server.net.rtmp.message

Examples of org.red5.server.net.rtmp.message.Header


    }
    RTMP rtmp = conn.getState();
    // Get the header size and length
    byte headerSize = RTMPUtils.decodeHeaderSize(headerValue, byteCount);
    int headerLength = RTMPUtils.getHeaderLength(headerSize);
    Header lastHeader = rtmp.getLastReadHeader(channelId);
    headerLength += byteCount - 1;
    switch (headerSize) {
      case HEADER_NEW:
      case HEADER_SAME_SOURCE:
      case HEADER_TIMER_CHANGE:
        if (remaining >= headerLength) {
          int timeValue = RTMPUtils.readUnsignedMediumInt(in);
          if (timeValue == 0xffffff) {
            headerLength += 4;
          }
        }
        break;
      case HEADER_CONTINUE:
        if (lastHeader != null && lastHeader.getExtendedTimestamp() != 0) {
          headerLength += 4;
        }
        break;
      default:
        throw new ProtocolException("Unexpected header size " + headerSize + " check for error");
    }
    if (remaining < headerLength) {
      log.trace("Header too small (hlen: {}), buffering. remaining: {}", headerLength, remaining);
      in.position(position);
      state.bufferDecoding(headerLength);
      return null;
    }
    // Move the position back to the start
    in.position(position);
    final Header header = decodeHeader(in, lastHeader);
    if (header == null) {
      throw new ProtocolException("Header is null, check for error");
    }
    rtmp.setLastReadHeader(channelId, header);
    // check to see if this is a new packets or continue decoding an existing one
    Packet packet = rtmp.getLastReadPacket(channelId);
    if (packet == null) {
      packet = new Packet(header.clone());
      rtmp.setLastReadPacket(channelId, packet);
    }
    final IoBuffer buf = packet.getData();
    final int readRemaining = header.getSize() - buf.position();
    final int chunkSize = rtmp.getReadChunkSize();
    final int readAmount = (readRemaining > chunkSize) ? chunkSize : readRemaining;
    if (in.remaining() < readAmount) {
      log.debug("Chunk too small, buffering ({},{})", in.remaining(), readAmount);
      // skip the position back to the start
      in.position(position);
      state.bufferDecoding(headerLength + readAmount);
      return null;
    }
    BufferUtils.put(buf, in, readAmount);
    if (buf.position() < header.getSize()) {
      state.continueDecoding();
      return null;
    }
    if (buf.position() > header.getSize()) {
      log.warn("Packet size expanded from {} to {} ({})", new Object[] { (header.getSize()), buf.position(), header });
    }
    buf.flip();
    try {
      final IRTMPEvent message = decodeMessage(conn, packet.getHeader(), buf);
      message.setHeader(packet.getHeader());
      // Unfortunately flash will, especially when resetting a video stream with a new key frame, sometime
      // send an earlier time stamp.  To avoid dropping it, we just give it the minimal increment since the
      // last message.  But to avoid relative time stamps being mis-computed, we don't reset the header we stored.
      final Header lastReadHeader = rtmp.getLastReadPacketHeader(channelId);
      if (lastReadHeader != null && (message instanceof AudioData || message instanceof VideoData)
          && RTMPUtils.compareTimestamps(lastReadHeader.getTimer(), packet.getHeader().getTimer()) >= 0) {
        log.trace("Non-monotonically increasing timestamps; type: {}; adjusting to {}; ts: {}; last: {}", new Object[] { header.getDataType(),
            lastReadHeader.getTimer() + 1, header.getTimer(), lastReadHeader.getTimer() });
        message.setTimestamp(lastReadHeader.getTimer() + 1);
      } else {
        message.setTimestamp(header.getTimer());
      }
      rtmp.setLastReadPacketHeader(channelId, packet.getHeader());
      packet.setMessage(message);
View Full Code Here


      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);
View Full Code Here

  }

  public void testHeaders() {
    // set dummy connection local to prevent npe when setting last header size below
    Red5.setConnectionLocal(RTMPConnManager.getInstance().createConnection(RTMPConnection.class));
    Header header = new Header();
    header.setChannelId((byte) 0x12);
    header.setDataType(TYPE_INVOKE);
    header.setStreamId(100);
    header.setTimer(2);
    header.setSize(320);
    IoBuffer buf = encoder.encodeHeader(header, null);
    buf.flip();
    log.debug(buf.getHexDump());
    assertNotNull(buf);
    Header result = decoder.decodeHeader(buf, null);
    assertEquals(header, result);
    Red5.setConnectionLocal(null);
  }
View Full Code Here

     
      if (!messageSent) {
        // Send blank audio packet to notify client about new position
        AudioData audio = new AudioData();
        audio.setTimestamp(seekPos);
        audio.setHeader(new Header());
        audio.getHeader().setTimer(seekPos);
        audio.getHeader().setTimerRelative(false);
        RTMPMessage audioMessage = new RTMPMessage();
        audioMessage.setBody(audio);
        lastMessage = audio;
View Full Code Here

      StatusMessage statusMsg = (StatusMessage) message;
      data.sendStatus(statusMsg.getBody());
    } else if (message instanceof RTMPMessage) {
      RTMPMessage rtmpMsg = (RTMPMessage) message;
      IRTMPEvent msg = rtmpMsg.getBody();
      Header header = new Header();
      int timestamp = streamTracker.add(msg);
      if (timestamp < 0) {
        log.warn("Skipping message with negative timestamp.");
        return;
      }
      header.setTimerRelative(streamTracker.isRelative());
      header.setTimer(timestamp);

      switch (msg.getDataType()) {
        case Constants.TYPE_STREAM_METADATA:
          Notify notify = new Notify(((Notify) msg).getData()
              .asReadOnlyBuffer());
          notify.setHeader(header);
          notify.setTimestamp(header.getTimer());
          data.write(notify);
          break;
        case Constants.TYPE_FLEX_STREAM_SEND:
          // TODO: okay to send this also to AMF0 clients?
          FlexStreamSend send = new FlexStreamSend(((Notify) msg).getData()
              .asReadOnlyBuffer());
          send.setHeader(header);
          send.setTimestamp(header.getTimer());
          data.write(send);
          break;
        case Constants.TYPE_VIDEO_DATA:
          VideoData videoData = new VideoData(((VideoData) msg)
              .getData().asReadOnlyBuffer());
          videoData.setHeader(header);
          videoData.setTimestamp(header.getTimer());
          video.write(videoData);
          break;
        case Constants.TYPE_AUDIO_DATA:
          AudioData audioData = new AudioData(((AudioData) msg)
              .getData().asReadOnlyBuffer());
          audioData.setHeader(header);
          audioData.setTimestamp(header.getTimer());
          audio.write(audioData);
          break;
        case Constants.TYPE_PING:
          Ping ping = new Ping(((Ping) msg).getValue1(), ((Ping) msg)
              .getValue2(), ((Ping) msg).getValue3(),
              ((Ping) msg).getValue4());
          header.setTimerRelative(false);
          header.setTimer(0);
          ping.setHeader(header);
          ping.setTimestamp(header.getTimer());
          conn.ping(ping);
          break;
        case Constants.TYPE_BYTES_READ:
          BytesRead bytesRead = new BytesRead(((BytesRead) msg)
              .getBytesRead());
          header.setTimerRelative(false);
          header.setTimer(0);
          bytesRead.setHeader(header);
          bytesRead.setTimestamp(header.getTimer());
          conn.getChannel((byte) 2).write(bytesRead);
          break;
        default:
          data.write(msg);
          break;
View Full Code Here

    IRTMPEvent message = null;
    try {

      final Packet packet = (Packet) in;
      message = packet.getMessage();
      final Header header = packet.getHeader();
      final Channel channel = conn.getChannel(header.getChannelId());
      final IClientStream stream = conn.getStreamById(header
          .getStreamId());

      if (log.isDebugEnabled()) {
        log.debug("Message recieved");
        log.debug("Stream Id: " + header);
        log.debug("Channel: " + channel);
      }

      // Thread local performance ? Should we benchmark
      Red5.setConnectionLocal(conn);

      // XXX: HACK HACK HACK to support stream ids
      BaseRTMPHandler.setStreamId(header.getStreamId());

      // Increase number of received messages
      conn.messageReceived();

      //if (message instanceof IRTMPEvent) {
      message.setSource(conn);
      //}

      switch (header.getDataType()) {
        case TYPE_CHUNK_SIZE:
          onChunkSize(conn, channel, header, (ChunkSize) message);
          break;

        case TYPE_INVOKE:
        case TYPE_FLEX_MESSAGE:
          onInvoke(conn, channel, header, (Invoke) message, (RTMP) state);
          if(message.getHeader().getStreamId()!=0
              && ((Invoke)message).getCall().getServiceName()==null
              && ACTION_PUBLISH.equals(((Invoke)message).getCall().getServiceMethodName())) {
            if (stream != null) {
              // Only dispatch if stream really was created
              ((IEventDispatcher) stream).dispatchEvent(message);
            }
          }
          break;

        case TYPE_NOTIFY: // just like invoke, but does not return
          if (((Notify) message).getData() != null && stream != null) {
            // Stream metadata
            ((IEventDispatcher) stream).dispatchEvent(message);
          } else {
            onInvoke(conn, channel, header, (Notify) message, (RTMP) state);
          }
          break;
         
        case TYPE_FLEX_STREAM_SEND:
          if (stream != null) {
            ((IEventDispatcher) stream).dispatchEvent(message);
          }
          break;
         
        case TYPE_PING:
          onPing(conn, channel, header, (Ping) message);
          break;

        case TYPE_BYTES_READ:
          onStreamBytesRead(conn, channel, header,
              (BytesRead) message);
          break;

        case TYPE_AUDIO_DATA:
        case TYPE_VIDEO_DATA:
          // log.info("in packet: "+source.getSize()+"
          // ts:"+source.getTimer());

          // NOTE: If we respond to "publish" with "NetStream.Publish.BadName",
          // the client sends a few stream packets before stopping. We need to
          // ignore them.
          if (stream != null)
            ((IEventDispatcher) stream).dispatchEvent(message);
          break;
        case TYPE_FLEX_SHARED_OBJECT:
        case TYPE_SHARED_OBJECT:
          onSharedObject(conn, channel, header,
              (SharedObjectMessage) message);
          break;
        default:
          log.debug("Unknown type: {}", header.getDataType());
      }
      if (message instanceof Unknown) {
        log.info("{}", message);
      }
    } catch (RuntimeException e) {
View Full Code Here

    try {

      final Packet packet = (Packet) in;
      final Object message = packet.getMessage();
      final Header source = packet.getHeader();

      log.debug("{}", source);
      log.debug("{}", message);

    } catch (RuntimeException e) {
View Full Code Here

     * @param event           Event data
     * @param streamId        Stream id
     */
    private void write(IRTMPEvent event, int streamId) {

    final Header header = new Header();
    final Packet packet = new Packet(header, event);

    header.setChannelId(id);
    header.setTimer(event.getTimestamp());
    header.setStreamId(streamId);
    header.setDataType(event.getDataType());
    if (event.getHeader() != null) {
      header.setTimerRelative(event.getHeader().isTimerRelative());
    }

    // should use RTMPConnection specific method..
    connection.write(packet);

View Full Code Here

     * @param packet      RTMP packet
     * @return            Encoded data
     */
    public ByteBuffer encodePacket(RTMP rtmp, Packet packet) {

    final Header header = packet.getHeader();
    final int channelId = header.getChannelId();
    final IRTMPEvent message = packet.getMessage();
    ByteBuffer data;

    if (message instanceof ChunkSize) {
      ChunkSize chunkSizeMsg = (ChunkSize) message;
      rtmp.setWriteChunkSize(chunkSizeMsg.getSize());
    }

    try {
      data = encodeMessage(rtmp, header, message);
    } finally {
      message.release();
    }

    if (data.position() != 0) {
      data.flip();
    } else {
      data.rewind();
    }
    header.setSize(data.limit());

    final Header lastHeader = rtmp.getLastWriteHeader(channelId);
    final int headerSize = calculateHeaderSize(header, lastHeader);
   
    rtmp.setLastWriteHeader(channelId, header);
    rtmp.setLastWritePacket(channelId, packet);
   
View Full Code Here

  @Override
  public void messageReceived(RTMPConnection conn, ProtocolState state, Object in) throws Exception {
    IRTMPEvent message = null;
    final Packet packet = (Packet) in;
    message = packet.getMessage();
    final Header header = packet.getHeader();
    final Channel channel = conn.getChannel(header.getChannelId());

    // Increase number of received messages
    conn.messageReceived();

    if (header.getDataType() == TYPE_BYTES_READ) {
      // TODO need to sync the bytes read on edge and origin
      onStreamBytesRead(conn, channel, header,
          (BytesRead) message);
    }

    if (header.getDataType() == TYPE_INVOKE) {
      final IServiceCall call = ((Invoke) message).getCall();
      final String action = call.getServiceMethodName();
      if (call.getServiceName() == null &&
          !conn.isConnected() &&
          action.equals(ACTION_CONNECT)) {
        handleConnect(conn, channel, header, (Invoke) message, (RTMP) state);
        return;
      }
    }

    switch (header.getDataType()) {
      case TYPE_CHUNK_SIZE:
      case TYPE_INVOKE:
      case TYPE_FLEX_MESSAGE:
      case TYPE_NOTIFY:
      case TYPE_AUDIO_DATA:
      case TYPE_VIDEO_DATA:
      case TYPE_FLEX_SHARED_OBJECT:
      case TYPE_SHARED_OBJECT:
      case TYPE_BYTES_READ:
        forwardPacket(conn, packet);
        break;
      case TYPE_PING:
        onPing(conn, channel, header, (Ping) message);
        break;

      default:
        if (log.isDebugEnabled()) {
          log.debug("Unknown type: "+header.getDataType());
        }
    }
    if (message instanceof Unknown) {
      log.info(message.toString());
    }
View Full Code Here

TOP

Related Classes of org.red5.server.net.rtmp.message.Header

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.