All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.xingshuangs.iot.protocol.rtp.model.RtpHeader Maven / Gradle / Ivy

Go to download

目前它只是一个物联网通信的工具,包含 1、西门子S7通信协议,支持西门子S1500,S1200,S400,S300,S200Smart,西门子机床828D; 2、Modbus通信协议,支持ModbusTcp, ModbusRtuOverTcp, ModbusAsciiOverTcp, ModbusTcpServer; 3、三菱Melsec(MC)通信协议,支持PLC iQ-R系列, Q/L系列, QnA系列, A系列, 目前只测试了L系列和FX5U; 4、RTSP, RTCP, RTP, H264, MP4 (FMP4)协议,RTSP + H264 + FMP4 + WebSocket + MSE + WEB; 5、基础字节数组解析转换工具;

The newest version!
/*
 * MIT License
 *
 * Copyright (c) 2021-2099 Oscura (xingshuang) 
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.github.xingshuangs.iot.protocol.rtp.model;


import com.github.xingshuangs.iot.common.IObjectByteArray;
import com.github.xingshuangs.iot.common.buff.ByteReadBuff;
import com.github.xingshuangs.iot.common.buff.ByteWriteBuff;
import com.github.xingshuangs.iot.utils.BooleanUtil;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * RTP数据包头
 * The RTP header has the following format:
 * 

* 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |V=2|P|X| CC |M| PT | sequence number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | timestamp | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | synchronization source (SSRC) identifier | * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ * | contributing source (CSRC) identifiers | * | .... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *

* RTP Header Extension * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | defined by profile | length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | header extension | * | .... | * * @author xingshuang */ @Data public class RtpHeader implements IObjectByteArray { /** * 版本(V):2 bits RTP版本号,现在用的是 * This field identifies the version of RTP. The version defined by * this specification is two (2). (The value 1 is used by the first * draft version of RTP and the value 0 is used by the protocol * initially implemented in the "vat" audio tool.) */ private int version; /** * 填充(P):1比特,1 bit 如果设置了该字段,报文的末尾会包含一个或多个填充字节,这些填充字节不是payload的内容。 * 最后一个填充字节标识了总共需要忽略多少个填充字节(包括自己) * If the padding bit is set, the packet contains one or more * additional padding octets at the end which are not part of the * payload. The last octet of the padding contains a count of how * many padding octets should be ignored, including itself. Padding * may be needed by some encryption algorithms with fixed block sizes * or for carrying several RTP packets in a lower-layer protocol data * unit. */ private boolean padding; /** * 1 bit 如果设置了该字段,那么头数据后跟着一个拓展数据 * If the extension bit is set, the fixed header MUST be followed by * exactly one header extension */ private boolean extension; /** * CSRC Count,共享媒体源个数,一般用于混音和混屏中,例如某个音频流是混合了其它音频后的数据,那么其它音频源就是该音频源的 CSRC * 4 bits CSRC列表的长度。 * The CSRC count contains the number of CSRC identifiers that follow * the fixed header. */ private int csrcCount; /** * Mark 标记位,对于不同的负载类型有不同含义,例如使用 RTP 荷载 H264 码流时,如果某个帧分成多个包进行传输,可以使用该位标记是否为帧的最后一个包 * 1 bit Marker会在预设中进行定义(预设和RTP的关系可以参考rfc3551,我的理解是预设是对RTP的补充,以达到某一类实际使用场景的需要), * 在报文流中用它来划分每一帧的边界。预设中可能会定义附加的marker,或者移除Marker来拓展payload type字段的长度。 * The interpretation of the marker is defined by a profile. It is * intended to allow significant events such as frame boundaries to * be marked in the packet stream. A profile MAY define additional * marker bits or specify that there is no marker bit by changing the * number of bits in the payload type field */ private boolean marker; /** * 7 bits 该字段定义RTP payload的格式和他在预设中的意义。上层应用可能会定义一个(静态的类型码<->payload格式)映射关系。 * 也可以用RTP协议外的方式来动态地定义payload类型。在一个RTP session中payload类型可能会改变,但是不应该用payload类型来区分不同的媒体流, * 正如之前所说,不同的媒体流应该通过不同session分别传输。 * This field identifies the format of the RTP payload and determines * its interpretation by the application. */ private int payloadType; /** * 16 bits 每发送一个RTP包该序列号+1,RTP包的接受者可以通过它来确定丢包情况并且利用它来重排包的顺序。 * 这个字段的初始值应该是随机的,这会让known-plaintext更加困难。 * The sequence number increments by one for each RTP data packet * sent, and may be used by the receiver to detect packet loss and to * restore packet sequence. */ private int sequenceNumber; /** * 32 bits 时间戳反映了RTP数据包生成第一块数据时的时刻 * The timestamp reflects the sampling instant of the first octet in * the RTP data packet. */ private long timestamp; /** * 32 bits 该字段用来确定数据的发送源。这个身份标识应该随机生成,并且要保证同一个RTP session中没有重复的SSRC。 * 虽然SSRC冲突的概率很小,但是每个RTP客户端都应该时刻警惕,如果发现冲突就要去解决。 * The SSRC field identifies the synchronization source. */ private long ssrc; /** * 0 ~ 15 items, 32 bits each CSRC list表示对该payload数据做出贡献的所有SSRC。 * 这个字段包含的SSRC数量由CC字段定义。如果有超过15个SSRC,只有15个可以被记录。 * The CSRC list identifies the contributing sources for the payload * contained in this packet. The number of identifiers is given by * the CC field. If there are more than 15 contributing sources, * only 15 can be identified. */ private List csrcList = new ArrayList<>(); /** * Extension header id. * 扩展头Id,2个字节 */ private int extensionHeaderId; /** * Extension header length. * 扩展头长度,2个字节 */ private int extensionHeaderLength; /** * Extension header content. * 扩展头的内容 */ private byte[] extensionHeaderContent = new byte[0]; @Override public int byteArrayLength() { int sum = 12 + this.csrcCount * 4; if (this.extension) { sum += 4 + this.extensionHeaderLength; } return sum; } @Override public byte[] toByteArray() { byte first = (byte) (((this.version << 6) & 0xC0) | BooleanUtil.setBit(5, this.padding) | BooleanUtil.setBit(4, this.extension) | (this.csrcCount & 0x0F)); byte second = (byte) (BooleanUtil.setBit(7, this.marker) | (this.payloadType & 0x7F)); ByteWriteBuff buff = ByteWriteBuff.newInstance(this.byteArrayLength()) .putByte(first) .putByte(second) .putShort(this.sequenceNumber) .putInteger(this.timestamp) .putInteger(this.ssrc); this.csrcList.forEach(buff::putInteger); if (this.extension) { buff.putShort(this.extensionHeaderId); buff.putShort(this.extensionHeaderLength); buff.putBytes(this.extensionHeaderContent); } return buff.getData(); } /** * Parses byte array and converts it to object. * * @param data byte array * @return RtcpHeader */ public static RtpHeader fromBytes(final byte[] data) { return fromBytes(data, 0); } /** * Parses byte array and converts it to object. * * @param data byte array * @param offset index offset * @return RtcpHeader */ public static RtpHeader fromBytes(final byte[] data, final int offset) { if (data.length < 12) { throw new IndexOutOfBoundsException("header, data length < 12"); } ByteReadBuff buff = new ByteReadBuff(data, offset); RtpHeader res = new RtpHeader(); byte aByte = buff.getByte(); res.version = (aByte >> 6) & 0x03; res.padding = BooleanUtil.getValue(aByte, 5); res.extension = BooleanUtil.getValue(aByte, 4); res.csrcCount = aByte & 0x0F; byte bByte = buff.getByte(); res.marker = BooleanUtil.getValue(bByte, 7); res.payloadType = bByte & 0x7F; res.sequenceNumber = buff.getUInt16(); res.timestamp = buff.getUInt32(); res.ssrc = buff.getUInt32(); for (int i = 0; i < res.csrcCount; i++) { res.csrcList.add(buff.getUInt32()); } // 扩展头 if (res.extension) { res.extensionHeaderId = buff.getUInt16(); res.extensionHeaderLength = buff.getUInt16() * 4; res.extensionHeaderContent = buff.getBytes(res.extensionHeaderLength); } return res; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy