2013-04-08 6 views
0

자바로 내 자신의 RTP 패킷을 만들려고합니다. 다른 패킷의 RTP 패킷과 함께 을 보내야합니다.시뮬레이션 된 rtp 패킷의 시퀀스 번호를 얻으십시오.

문제 : 내 패킷 의 VoIP의 RTP 패킷에 일련 번호 시리즈가 did'nt 때문에

수신기가, 내 패킷은 패킷 손실로 검출되었다.

질문 :

어떻게 난 내 시뮬레이션 RTP 패킷에 대한 일련의 시퀀스 번호를받을 수 있나요?

답변

1

시퀀스 번호는 RTP 패킷의 3 번째 및 4 번째 옥텟에서 찾을 수 있습니다.

RTP 시퀀스 번호는 연속이어야합니다. 다른 응용 프로그램에서 보낸 다른 스트림에 RTP 패킷을 삽입하려는 경우 수신 응용 프로그램은 순서가 잘못된 패킷 (번호가 연속적이지 않은 경우) 또는 중복 패킷 (시퀀스 번호가 동일한 경우)을 감지합니다. 두 경우 모두 패킷 손실이 발생할 가능성이 높습니다. 전체 세부 사항

보기 RFC 3550 Mobicents 프로젝트 구현 아래 참조

1

(특히, 패킷 손실의 검출을 포함하는 알고리즘을 설명 A 부록).

/* * 보스, 가정 전문의 오픈 소스 * 저작권 2011, 레드햇, Inc. 및 개별 기여자 * @authors 태그에 의해. 개별 기여자의 전체 목록 *에 대한 배포판의 copyright.txt를 참조하십시오. * * 이것은 무료 소프트웨어입니다. GNU 약소 일반 공중 사용 허가서 (GNU Lesser General Public License)의 규정에 따라 *을 재배포 및 수정하거나 자유 소프트웨어 재단이 발행 한 *으로 수정할 수 있습니다. 버전 2.1 * 라이센스 또는 (귀하의 선택에 따라) 이후 버전. * *이 소프트웨어는 유용 할 것이라는 희망으로 배포되었지만 * 보증은 제공되지 않습니다. * 상품성 또는 특정 목적에의 적합성에 대한 묵시적인 보증도 제공하지 않습니다. 자세한 내용은 GNU * 약소 일반 공중 라이선스를 참조하십시오. * *이 소프트웨어와 함께 GNU 약소 일반본 * 라이센스를 받아야합니다. 그렇지 않은 경우 무료 * Software Foundation, Inc., 51 Franklin St, Boston, MA * 02110-1301 USA에 문의하거나 FSF 사이트 http://www.fsf.org을 참조하십시오. */

패키지 org.mobicents.media.server.impl.rtp;

import java.io.Serializable; import java.nio.ByteBuffer;/**

* 고정 된 RTP 헤더로 이루어지는 데이터 패킷, 소스 기여 의 비어 목록 * 및 페이로드 데이터를 포함한다. 일부 기본 프로토콜은 정의 될 RTP 패킷의 캡슐화를 요구할 수도 있습니다 ( *).밀봉 * 법에 의해 허용되는 경우, 일반적으로 하나 *이 기본 프로토콜의 패킷은 * 그러나 여러 RTP 패킷이 포함될 수있다 를 하나의 RTP 패킷을 포함 * * @author 올렉 Kulikov 보낸 * @author 미트 bhayani */ 공용 클래스 RtpPacket는 Serializable {

//underlying buffer 
private ByteBuffer buffer; 

/** 
* Creates new instance of RTP packet. 
* 
* @param capacity the maximum available size for packet. 
* @param allocateDirect if false then packet will use backing array to hold 
* raw data and if true the direct buffer will be allocated 
*/ 
public RtpPacket(int capacity, boolean allocateDirect) {   
    buffer = allocateDirect ? 
     ByteBuffer.allocateDirect(capacity) : 
     ByteBuffer.allocate(capacity); 
} 

/** 
* Provides access to the underlying buffer. 
* 
* @return the underlying buffer instance. 
*/ 
protected ByteBuffer getBuffer() { 
    return buffer; 
} 

/** 
* Verion field. 
* 
* 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.) 
* 
* @return the version value. 
*/ 
public int getVersion() { 
    return (buffer.get(0) & 0xC0) >> 6; 
} 

/** 
* Countributing source field. 
* 
* 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 may be identified. CSRC identifiers areinserted by 
* mixers, using the SSRC identifiers of contributing 
* sources. For example, for audio packets the SSRC identifiers of 
* all sources that were mixed together to create a packet are 
* listed, allowing correct talker indication at the receiver. 
* 
* @return synchronization source. 
*/ 
public int getContributingSource() { 
    return buffer.get(0) & 0x0F; 
} 

/** 
* Padding indicator. 
* 
* 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. 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. 
* 
* @return true if padding bit set. 
*/ 
public boolean hasPadding() { 
    return (buffer.get(0) & 0x20) == 0x020; 
} 

/** 
* Extension indicator. 
* 
* If the extension bit is set, the fixed header is followed by 
* exactly one header extension. 
* 
* @return true if extension bit set. 
*/ 
public boolean hasExtensions() { 
    return (buffer.get(0) & 0x10) == 0x010; 
} 

/** 
* Marker bit. 
* 
* 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 
* 
* @return true if marker set. 
*/ 
public boolean getMarker() { 
    return (buffer.get(1) & 0xff & 0x80) == 0x80; 
} 

/** 
* Payload type. 
* 
* This field identifies the format of the RTP payload and 
* determines its interpretation by the application. A profile 
* specifies a default static mapping of payload type codes to 
* payload formats. Additional payload type codes may be defined 
* dynamically through non-RTP means 
* 
* @return integer value of payload type. 
*/ 
public int getPayloadType() { 
    return (buffer.get(1) & 0xff & 0x7f); 
} 

/** 
* Sequence number field. 
* 
* 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. The initial value of the sequence 
* number is random (unpredictable) to make known-plaintext attacks 
* on encryption more difficult, even if the source itself does not 
* encrypt, because the packets may flow through a translator that 
* does. 
* 
* @return the sequence number value. 
*/ 
public int getSeqNumber() { 


    short sn = buffer.getShort(2);  
    return (sn & 0xffff); 

} 

/** 
* Timestamp field. 
* 
* The timestamp reflects the sampling instant of the first octet 
* in the RTP data packet. The sampling instant must be derived 
* from a clock that increments monotonically and linearly in time 
* to allow synchronization and jitter calculations. 
* The resolution of the clock must be sufficient for the 
* desired synchronization accuracy and for measuring packet 
* arrival jitter (one tick per video frame is typically not 
* sufficient). The clock frequency is dependent on the format of 
* data carried as payload and is specified statically in the 
* profile or payload format specification that defines the format, 
* or may be specified dynamically for payload formats defined 
* through non-RTP means. If RTP packets are generated 
* periodically, the nominal sampling instant as determined from 
* the sampling clock is to be used, not a reading of the system 
* clock. As an example, for fixed-rate audio the timestamp clock 
* would likely increment by one for each sampling period. If an 
* audio application reads blocks covering 160 sampling periods 
* from the input device, the timestamp would be increased by 160 
* for each such block, regardless of whether the block is 
* transmitted in a packet or dropped as silent. 
* 
* The initial value of the timestamp is random, as for the sequence 
* number. Several consecutive RTP packets may have equal timestamps if 
* they are (logically) generated at once, e.g., belong to the same 
* video frame. Consecutive RTP packets may contain timestamps that are 
* not monotonic if the data is not transmitted in the order it was 
* sampled, as in the case of MPEG interpolated video frames. (The 
* sequence numbers of the packets as transmitted will still be 
* monotonic.) 
* 
* @return timestamp value 
*/ 
public long getTimestamp() { 
    return ((long)(buffer.get(4) & 0xff) << 24) | 
      ((long)(buffer.get(5) & 0xff) << 16) | 
      ((long)(buffer.get(6) & 0xff) << 8) | 
      ((long)(buffer.get(7) & 0xff)); 
} 

/** 
* Synchronization source field. 
* 
* The SSRC field identifies the synchronization source. This 
* identifier is chosen randomly, with the intent that no two 
* synchronization sources within the same RTP session will have 
* the same SSRC identifier. Although the 
* probability of multiple sources choosing the same identifier is 
* low, all RTP implementations must be prepared to detect and 
* resolve collisions. Section 8 describes the probability of 
* collision along with a mechanism for resolving collisions and 
* detecting RTP-level forwarding loops based on the uniqueness of 
* the SSRC identifier. If a source changes its source transport 
* address, it must also choose a new SSRC identifier to avoid 
* being interpreted as a looped source. 
* 
* @return the sysncronization source 
*/ 
public long getSyncSource() { 
    return ((long)(buffer.get(8) & 0xff) << 24) | 
      ((long)(buffer.get(9) & 0xff) << 16) | 
      ((long)(buffer.get(10) & 0xff) << 8) | 
      ((long)(buffer.get(11) & 0xff)); 
} 

/** 
* The number of bytes transmitted by RTP in a packet. 
* 
* @return the number of bytes. 
*/ 
public int getPayloadLength() { 
    return buffer.limit() - 12; 
} 

/** 
* Reads the data transported by RTP in a packet, for example 
* audio samples or compressed video data. 
* 
* @param buff the buffer used for reading 
* @param offset the initial offset inside buffer. 
*/ 
public void getPayload(byte[] buff, int offset) { 
    buffer.position(12); 
    buffer.get(buff, offset, buffer.limit() - 12); 
} 

/** 
* Encapsulates data into the packet for transmission via RTP. 
* 
* @param mark mark field 
* @param payloadType payload type field. 
* @param seqNumber sequence number field 
* @param timestamp timestamp field 
* @param ssrc synchronization source field 
* @param data data buffer 
* @param offset offset in the data buffer 
* @param len the number of bytes 
*/ 
public void wrap(boolean mark, int payloadType, int seqNumber, long timestamp, long ssrc, byte[] data, int offset, int len) { 
    buffer.clear(); 
    buffer.rewind(); 

    //no extensions, paddings and cc 
    buffer.put((byte)0x80); 

    byte b = (byte) (payloadType); 
    if (mark) { 
     b = (byte) (b | 0x80); 
    } 

    buffer.put(b); 

    //sequence number 
    buffer.put((byte) ((seqNumber & 0xFF00) >> 8)); 
    buffer.put((byte) (seqNumber & 0x00FF)); 

    //timestamp 
    buffer.put((byte) ((timestamp & 0xFF000000) >> 24)); 
    buffer.put((byte) ((timestamp & 0x00FF0000) >> 16)); 
    buffer.put((byte) ((timestamp & 0x0000FF00) >> 8)); 
    buffer.put((byte) ((timestamp & 0x000000FF))); 

    //ssrc 
    buffer.put((byte) ((ssrc & 0xFF000000) >> 24)); 
    buffer.put((byte) ((ssrc & 0x00FF0000) >> 16)); 
    buffer.put((byte) ((ssrc & 0x0000FF00) >> 8)); 
    buffer.put((byte) ((ssrc & 0x000000FF))); 

    buffer.put(data, offset, len); 
    buffer.flip(); 
    buffer.rewind(); 
} 

@Override 
public String toString() { 
    return "RTP Packet[marker=" + getMarker() + ", seq=" + getSeqNumber() + 
      ", timestamp=" + getTimestamp() + ", payload_size=" + getPayloadLength() + 
      ", payload=" + getPayloadType() + "]"; 
} 

}

를 구현
관련 문제