正在显示
5 个修改的文件
包含
349 行增加
和
4 行删除
| @@ -33,19 +33,24 @@ using namespace std; | @@ -33,19 +33,24 @@ using namespace std; | ||
| 33 | #include <srs_kernel_log.hpp> | 33 | #include <srs_kernel_log.hpp> |
| 34 | #include <srs_app_utility.hpp> | 34 | #include <srs_app_utility.hpp> |
| 35 | #include <srs_core_autofree.hpp> | 35 | #include <srs_core_autofree.hpp> |
| 36 | +#include <srs_kernel_stream.hpp> | ||
| 37 | +#include <srs_kernel_buffer.hpp> | ||
| 36 | 38 | ||
| 37 | #ifdef SRS_AUTO_STREAM_CASTER | 39 | #ifdef SRS_AUTO_STREAM_CASTER |
| 38 | 40 | ||
| 39 | -SrsRtpConn::SrsRtpConn(SrsRtspConn* r, int p) | 41 | +SrsRtpConn::SrsRtpConn(SrsRtspConn* r, int p, int sid) |
| 40 | { | 42 | { |
| 41 | rtsp = r; | 43 | rtsp = r; |
| 42 | _port = p; | 44 | _port = p; |
| 45 | + stream_id = sid; | ||
| 43 | listener = new SrsUdpListener(this, p); | 46 | listener = new SrsUdpListener(this, p); |
| 47 | + cache = new SrsRtpPacket(); | ||
| 44 | } | 48 | } |
| 45 | 49 | ||
| 46 | SrsRtpConn::~SrsRtpConn() | 50 | SrsRtpConn::~SrsRtpConn() |
| 47 | { | 51 | { |
| 48 | srs_freep(listener); | 52 | srs_freep(listener); |
| 53 | + srs_freep(cache); | ||
| 49 | } | 54 | } |
| 50 | 55 | ||
| 51 | int SrsRtpConn::port() | 56 | int SrsRtpConn::port() |
| @@ -61,6 +66,53 @@ int SrsRtpConn::listen() | @@ -61,6 +66,53 @@ int SrsRtpConn::listen() | ||
| 61 | int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) | 66 | int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) |
| 62 | { | 67 | { |
| 63 | int ret = ERROR_SUCCESS; | 68 | int ret = ERROR_SUCCESS; |
| 69 | + | ||
| 70 | + if (true) { | ||
| 71 | + SrsStream stream; | ||
| 72 | + | ||
| 73 | + if ((ret = stream.initialize(buf, nb_buf)) != ERROR_SUCCESS) { | ||
| 74 | + return ret; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + SrsRtpPacket pkt; | ||
| 78 | + if ((ret = pkt.decode(&stream)) != ERROR_SUCCESS) { | ||
| 79 | + srs_error("rtsp: decode rtp packet failed. ret=%d", ret); | ||
| 80 | + return ret; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + if (pkt.chunked) { | ||
| 84 | + if (!cache) { | ||
| 85 | + cache = new SrsRtpPacket(); | ||
| 86 | + } | ||
| 87 | + cache->copy(&pkt); | ||
| 88 | + cache->payload->append(pkt.payload->bytes(), pkt.payload->length()); | ||
| 89 | + if (!cache->completed) { | ||
| 90 | + srs_trace("rtsp: rtp chunked %dB, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB", | ||
| 91 | + nb_buf, cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc, | ||
| 92 | + cache->payload->length() | ||
| 93 | + ); | ||
| 94 | + return ret; | ||
| 95 | + } | ||
| 96 | + } else { | ||
| 97 | + srs_freep(cache); | ||
| 98 | + cache = new SrsRtpPacket(); | ||
| 99 | + cache->reap(&pkt); | ||
| 100 | + } | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + srs_trace("rtsp: rtp %dB, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB, chunked=%d", | ||
| 104 | + nb_buf, cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc, | ||
| 105 | + cache->payload->length(), cache->chunked | ||
| 106 | + ); | ||
| 107 | + | ||
| 108 | + // always free it. | ||
| 109 | + SrsAutoFree(SrsRtpPacket, cache); | ||
| 110 | + | ||
| 111 | + if ((ret = rtsp->on_rtp_packet(cache)) != ERROR_SUCCESS) { | ||
| 112 | + srs_error("rtsp: process rtp packet failed. ret=%d", ret); | ||
| 113 | + return ret; | ||
| 114 | + } | ||
| 115 | + | ||
| 64 | return ret; | 116 | return ret; |
| 65 | } | 117 | } |
| 66 | 118 | ||
| @@ -162,10 +214,10 @@ int SrsRtspConn::do_cycle() | @@ -162,10 +214,10 @@ int SrsRtspConn::do_cycle() | ||
| 162 | SrsRtpConn* rtp = NULL; | 214 | SrsRtpConn* rtp = NULL; |
| 163 | if (req->stream_id == video_id) { | 215 | if (req->stream_id == video_id) { |
| 164 | srs_freep(video_rtp); | 216 | srs_freep(video_rtp); |
| 165 | - rtp = video_rtp = new SrsRtpConn(this, lpm); | 217 | + rtp = video_rtp = new SrsRtpConn(this, lpm, video_id); |
| 166 | } else { | 218 | } else { |
| 167 | srs_freep(audio_rtp); | 219 | srs_freep(audio_rtp); |
| 168 | - rtp = audio_rtp = new SrsRtpConn(this, lpm); | 220 | + rtp = audio_rtp = new SrsRtpConn(this, lpm, audio_id); |
| 169 | } | 221 | } |
| 170 | if ((ret = rtp->listen()) != ERROR_SUCCESS) { | 222 | if ((ret = rtp->listen()) != ERROR_SUCCESS) { |
| 171 | srs_error("rtsp: rtp listen at port=%d failed. ret=%d", lpm, ret); | 223 | srs_error("rtsp: rtp listen at port=%d failed. ret=%d", lpm, ret); |
| @@ -210,6 +262,12 @@ int SrsRtspConn::do_cycle() | @@ -210,6 +262,12 @@ int SrsRtspConn::do_cycle() | ||
| 210 | return ret; | 262 | return ret; |
| 211 | } | 263 | } |
| 212 | 264 | ||
| 265 | +int SrsRtspConn::on_rtp_packet(SrsRtpPacket* pkt) | ||
| 266 | +{ | ||
| 267 | + int ret = ERROR_SUCCESS; | ||
| 268 | + return ret; | ||
| 269 | +} | ||
| 270 | + | ||
| 213 | int SrsRtspConn::cycle() | 271 | int SrsRtspConn::cycle() |
| 214 | { | 272 | { |
| 215 | // serve the rtsp client. | 273 | // serve the rtsp client. |
| @@ -45,6 +45,7 @@ class SrsRtspConn; | @@ -45,6 +45,7 @@ class SrsRtspConn; | ||
| 45 | class SrsRtspStack; | 45 | class SrsRtspStack; |
| 46 | class SrsRtspCaster; | 46 | class SrsRtspCaster; |
| 47 | class SrsConfDirective; | 47 | class SrsConfDirective; |
| 48 | +class SrsRtpPacket; | ||
| 48 | 49 | ||
| 49 | /** | 50 | /** |
| 50 | * a rtp connection which transport a stream. | 51 | * a rtp connection which transport a stream. |
| @@ -54,9 +55,11 @@ class SrsRtpConn: public ISrsUdpHandler | @@ -54,9 +55,11 @@ class SrsRtpConn: public ISrsUdpHandler | ||
| 54 | private: | 55 | private: |
| 55 | SrsUdpListener* listener; | 56 | SrsUdpListener* listener; |
| 56 | SrsRtspConn* rtsp; | 57 | SrsRtspConn* rtsp; |
| 58 | + SrsRtpPacket* cache; | ||
| 59 | + int stream_id; | ||
| 57 | int _port; | 60 | int _port; |
| 58 | public: | 61 | public: |
| 59 | - SrsRtpConn(SrsRtspConn* r, int p); | 62 | + SrsRtpConn(SrsRtspConn* r, int p, int sid); |
| 60 | virtual ~SrsRtpConn(); | 63 | virtual ~SrsRtpConn(); |
| 61 | public: | 64 | public: |
| 62 | virtual int port(); | 65 | virtual int port(); |
| @@ -103,6 +106,9 @@ public: | @@ -103,6 +106,9 @@ public: | ||
| 103 | virtual int serve(); | 106 | virtual int serve(); |
| 104 | private: | 107 | private: |
| 105 | virtual int do_cycle(); | 108 | virtual int do_cycle(); |
| 109 | +// internal methods | ||
| 110 | +public: | ||
| 111 | + virtual int on_rtp_packet(SrsRtpPacket* pkt); | ||
| 106 | // interface ISrsThreadHandler | 112 | // interface ISrsThreadHandler |
| 107 | public: | 113 | public: |
| 108 | virtual int cycle(); | 114 | virtual int cycle(); |
| @@ -144,6 +144,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -144,6 +144,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 144 | #define ERROR_RTMP_MIC_CACHE_OVERFLOW 2041 | 144 | #define ERROR_RTMP_MIC_CACHE_OVERFLOW 2041 |
| 145 | #define ERROR_RTSP_TOKEN_NOT_NORMAL 2042 | 145 | #define ERROR_RTSP_TOKEN_NOT_NORMAL 2042 |
| 146 | #define ERROR_RTSP_REQUEST_HEADER_EOF 2043 | 146 | #define ERROR_RTSP_REQUEST_HEADER_EOF 2043 |
| 147 | +#define ERROR_RTP_HEADER_CORRUPT 2044 | ||
| 147 | // | 148 | // |
| 148 | // system control message, | 149 | // system control message, |
| 149 | // not an error, but special control logic. | 150 | // not an error, but special control logic. |
| @@ -34,6 +34,7 @@ using namespace std; | @@ -34,6 +34,7 @@ using namespace std; | ||
| 34 | #include <srs_kernel_consts.hpp> | 34 | #include <srs_kernel_consts.hpp> |
| 35 | #include <srs_core_autofree.hpp> | 35 | #include <srs_core_autofree.hpp> |
| 36 | #include <srs_kernel_utility.hpp> | 36 | #include <srs_kernel_utility.hpp> |
| 37 | +#include <srs_kernel_stream.hpp> | ||
| 37 | 38 | ||
| 38 | #ifdef SRS_AUTO_STREAM_CASTER | 39 | #ifdef SRS_AUTO_STREAM_CASTER |
| 39 | 40 | ||
| @@ -118,6 +119,121 @@ std::string srs_generate_rtsp_method_str(SrsRtspMethod method) | @@ -118,6 +119,121 @@ std::string srs_generate_rtsp_method_str(SrsRtspMethod method) | ||
| 118 | } | 119 | } |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 122 | +SrsRtpPacket::SrsRtpPacket() | ||
| 123 | +{ | ||
| 124 | + version = 2; | ||
| 125 | + padding = 0; | ||
| 126 | + extension = 0; | ||
| 127 | + csrc_count = 0; | ||
| 128 | + marker = 1; | ||
| 129 | + | ||
| 130 | + payload_type = 0; | ||
| 131 | + sequence_number = 0; | ||
| 132 | + timestamp = 0; | ||
| 133 | + ssrc = 0; | ||
| 134 | + | ||
| 135 | + payload = new SrsSimpleBuffer(); | ||
| 136 | + chunked = false; | ||
| 137 | + completed = false; | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | +SrsRtpPacket::~SrsRtpPacket() | ||
| 141 | +{ | ||
| 142 | + srs_freep(payload); | ||
| 143 | +} | ||
| 144 | + | ||
| 145 | +void SrsRtpPacket::copy(SrsRtpPacket* src) | ||
| 146 | +{ | ||
| 147 | + version = src->version; | ||
| 148 | + padding = src->padding; | ||
| 149 | + extension = src->extension; | ||
| 150 | + csrc_count = src->csrc_count; | ||
| 151 | + marker = src->marker; | ||
| 152 | + payload_type = src->payload_type; | ||
| 153 | + sequence_number = src->sequence_number; | ||
| 154 | + timestamp = src->timestamp; | ||
| 155 | + ssrc = src->ssrc; | ||
| 156 | + | ||
| 157 | + chunked = src->chunked; | ||
| 158 | + completed = src->completed; | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +void SrsRtpPacket::reap(SrsRtpPacket* src) | ||
| 162 | +{ | ||
| 163 | + copy(src); | ||
| 164 | + | ||
| 165 | + payload = src->payload; | ||
| 166 | + src->payload = NULL; | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | +int SrsRtpPacket::decode(SrsStream* stream) | ||
| 170 | +{ | ||
| 171 | + int ret = ERROR_SUCCESS; | ||
| 172 | + | ||
| 173 | + // 12bytes header, atleast 2bytes content. | ||
| 174 | + if (!stream->require(14)) { | ||
| 175 | + ret = ERROR_RTP_HEADER_CORRUPT; | ||
| 176 | + srs_error("rtsp: rtp header corrupt. ret=%d", ret); | ||
| 177 | + return ret; | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + int8_t vv = stream->read_1bytes(); | ||
| 181 | + version = (vv >> 6) & 0x03; | ||
| 182 | + padding = (vv >> 5) & 0x01; | ||
| 183 | + extension = (vv >> 4) & 0x01; | ||
| 184 | + csrc_count = vv & 0x0f; | ||
| 185 | + | ||
| 186 | + int8_t mv = stream->read_1bytes(); | ||
| 187 | + marker = (mv >> 7) & 0x01; | ||
| 188 | + payload_type = mv & 0x7f; | ||
| 189 | + | ||
| 190 | + sequence_number = stream->read_2bytes(); | ||
| 191 | + timestamp = stream->read_4bytes(); | ||
| 192 | + ssrc = stream->read_4bytes(); | ||
| 193 | + | ||
| 194 | + // frame type | ||
| 195 | + // 0... .... reserverd | ||
| 196 | + // .11. .... NALU[0]&0x60 | ||
| 197 | + // ...1 11.. FU indicator | ||
| 198 | + // .... ..00 reserverd | ||
| 199 | + int8_t ftv = stream->read_1bytes(); | ||
| 200 | + int8_t nalu_0x60 = ftv & 0x60; | ||
| 201 | + int8_t fu_indicator = ftv & 0x1c; | ||
| 202 | + | ||
| 203 | + // nri, whatever | ||
| 204 | + // 10.. .... first chunk. | ||
| 205 | + // 00.. .... continous chunk. | ||
| 206 | + // 01.. .... last chunk. | ||
| 207 | + // ...1 1111 NALU[0]&0x1f | ||
| 208 | + int8_t nriv = stream->read_1bytes(); | ||
| 209 | + bool first_chunk = (nriv & 0xC0) == 0x80; | ||
| 210 | + bool last_chunk = (nriv & 0xC0) == 0x40; | ||
| 211 | + bool contious_chunk = (nriv & 0xC0) == 0x00; | ||
| 212 | + int8_t nalu_0x1f = nriv & 0x1f; | ||
| 213 | + | ||
| 214 | + // chunked, generate the first byte NALU. | ||
| 215 | + if (fu_indicator == 0x1c && (first_chunk || last_chunk || contious_chunk)) { | ||
| 216 | + chunked = true; | ||
| 217 | + completed = last_chunk; | ||
| 218 | + | ||
| 219 | + // generate and append the first byte NALU. | ||
| 220 | + if (first_chunk) { | ||
| 221 | + int8_t nalu_byte0 = nalu_0x60 | nalu_0x1f; | ||
| 222 | + payload->append((char*)&nalu_byte0, 1); | ||
| 223 | + } | ||
| 224 | + | ||
| 225 | + payload->append(stream->data() + stream->pos(), stream->size() - stream->pos()); | ||
| 226 | + return ret; | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + // no chunked, append to payload. | ||
| 230 | + stream->skip(-2); | ||
| 231 | + payload->append(stream->data() + stream->pos(), stream->size() - stream->pos()); | ||
| 232 | + completed = true; | ||
| 233 | + | ||
| 234 | + return ret; | ||
| 235 | +} | ||
| 236 | + | ||
| 121 | SrsRtspSdp::SrsRtspSdp() | 237 | SrsRtspSdp::SrsRtspSdp() |
| 122 | { | 238 | { |
| 123 | state = SrsRtspSdpStateOthers; | 239 | state = SrsRtspSdpStateOthers; |
| @@ -37,6 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -37,6 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 37 | 37 | ||
| 38 | #ifdef SRS_AUTO_STREAM_CASTER | 38 | #ifdef SRS_AUTO_STREAM_CASTER |
| 39 | 39 | ||
| 40 | +class SrsStream; | ||
| 40 | class SrsSimpleBuffer; | 41 | class SrsSimpleBuffer; |
| 41 | class ISrsProtocolReaderWriter; | 42 | class ISrsProtocolReaderWriter; |
| 42 | 43 | ||
| @@ -147,6 +148,169 @@ enum SrsRtspTokenState | @@ -147,6 +148,169 @@ enum SrsRtspTokenState | ||
| 147 | }; | 148 | }; |
| 148 | 149 | ||
| 149 | /** | 150 | /** |
| 151 | +* the rtp packet. | ||
| 152 | +* 5. RTP Data Transfer Protocol, @see rtp-rfc3550-2003.pdf, page 12 | ||
| 153 | +*/ | ||
| 154 | +class SrsRtpPacket | ||
| 155 | +{ | ||
| 156 | +public: | ||
| 157 | + /** | ||
| 158 | + * version (V): 2 bits | ||
| 159 | + * This eld identies the version of RTP. The version dened by this specication is two (2). | ||
| 160 | + * (The value 1 is used by the rst draft version of RTP and the value 0 is used by the protocol | ||
| 161 | + * initially implemented in the \vat" audio tool.) | ||
| 162 | + */ | ||
| 163 | + int8_t version; //2bits | ||
| 164 | + /** | ||
| 165 | + * padding (P): 1 bit | ||
| 166 | + * If the padding bit is set, the packet contains one or more additional padding octets at the | ||
| 167 | + * end which are not part of the payload. The last octet of the padding contains a count of | ||
| 168 | + * how many padding octets should be ignored, including itself. Padding may be needed by | ||
| 169 | + * some encryption algorithms with xed block sizes or for carrying several RTP packets in a | ||
| 170 | + * lower-layer protocol data unit. | ||
| 171 | + */ | ||
| 172 | + int8_t padding; //1bit | ||
| 173 | + /** | ||
| 174 | + * extension (X): 1 bit | ||
| 175 | + * If the extension bit is set, the xed header must be followed by exactly one header extension, | ||
| 176 | + * with a format dened in Section 5.3.1. | ||
| 177 | + */ | ||
| 178 | + int8_t extension; //1bit | ||
| 179 | + /** | ||
| 180 | + * CSRC count (CC): 4 bits | ||
| 181 | + * The CSRC count contains the number of CSRC identiers that follow the xed header. | ||
| 182 | + */ | ||
| 183 | + int8_t csrc_count; //4bits | ||
| 184 | + /** | ||
| 185 | + * marker (M): 1 bit | ||
| 186 | + * The interpretation of the marker is dened by a prole. It is intended to allow signicant | ||
| 187 | + * events such as frame boundaries to be marked in the packet stream. A prole may dene | ||
| 188 | + * additional marker bits or specify that there is no marker bit by changing the number of bits | ||
| 189 | + * in the payload type eld (see Section 5.3). | ||
| 190 | + */ | ||
| 191 | + int8_t marker; //1bit | ||
| 192 | + /** | ||
| 193 | + * payload type (PT): 7 bits | ||
| 194 | + * This eld identies the format of the RTP payload and determines its interpretation by the | ||
| 195 | + * application. A prole may specify a default static mapping of payload type codes to payload | ||
| 196 | + * formats. Additional payload type codes may be dened dynamically through non-RTP means | ||
| 197 | + * (see Section 3). A set of default mappings for audio and video is specied in the companion | ||
| 198 | + * RFC 3551 [1]. An RTP source may change the payload type during a session, but this eld | ||
| 199 | + * should not be used for multiplexing separate media streams (see Section 5.2). | ||
| 200 | + * A receiver must ignore packets with payload types that it does not understand. | ||
| 201 | + */ | ||
| 202 | + int8_t payload_type; //7bits | ||
| 203 | + /** | ||
| 204 | + * sequence number: 16 bits | ||
| 205 | + * The sequence number increments by one for each RTP data packet sent, and may be used | ||
| 206 | + * by the receiver to detect packet loss and to restore packet sequence. The initial value of the | ||
| 207 | + * sequence number should be random (unpredictable) to make known-plaintext attacks on | ||
| 208 | + * encryption more dicult, even if the source itself does not encrypt according to the method | ||
| 209 | + * in Section 9.1, because the packets may flow through a translator that does. Techniques for | ||
| 210 | + * choosing unpredictable numbers are discussed in [17]. | ||
| 211 | + */ | ||
| 212 | + u_int16_t sequence_number; //16bits | ||
| 213 | + /** | ||
| 214 | + * timestamp: 32 bits | ||
| 215 | + * The timestamp reflects the sampling instant of the rst octet in the RTP data packet. The | ||
| 216 | + * sampling instant must be derived from a clock that increments monotonically and linearly | ||
| 217 | + * in time to allow synchronization and jitter calculations (see Section 6.4.1). The resolution | ||
| 218 | + * of the clock must be sucient for the desired synchronization accuracy and for measuring | ||
| 219 | + * packet arrival jitter (one tick per video frame is typically not sucient). The clock frequency | ||
| 220 | + * is dependent on the format of data carried as payload and is specied statically in the prole | ||
| 221 | + * or payload format specication that denes the format, or may be specied dynamically for | ||
| 222 | + * payload formats dened through non-RTP means. If RTP packets are generated periodically, | ||
| 223 | + * the nominal sampling instant as determined from the sampling clock is to be used, not a | ||
| 224 | + * reading of the system clock. As an example, for xed-rate audio the timestamp clock would | ||
| 225 | + * likely increment by one for each sampling period. If an audio application reads blocks covering | ||
| 226 | + * 160 sampling periods from the input device, the timestamp would be increased by 160 for | ||
| 227 | + * each such block, regardless of whether the block is transmitted in a packet or dropped as | ||
| 228 | + * silent. | ||
| 229 | + * | ||
| 230 | + * The initial value of the timestamp should be random, as for the sequence number. Several | ||
| 231 | + * consecutive RTP packets will have equal timestamps if they are (logically) generated at once, | ||
| 232 | + * e.g., belong to the same video frame. Consecutive RTP packets may contain timestamps that | ||
| 233 | + * are not monotonic if the data is not transmitted in the order it was sampled, as in the case | ||
| 234 | + * of MPEG interpolated video frames. (The sequence numbers of the packets as transmitted | ||
| 235 | + * will still be monotonic.) | ||
| 236 | + * | ||
| 237 | + * RTP timestamps from dierent media streams may advance at dierent rates and usually | ||
| 238 | + * have independent, random osets. Therefore, although these timestamps are sucient to | ||
| 239 | + * reconstruct the timing of a single stream, directly comparing RTP timestamps from dierent | ||
| 240 | + * media is not eective for synchronization. Instead, for each medium the RTP timestamp | ||
| 241 | + * is related to the sampling instant by pairing it with a timestamp from a reference clock | ||
| 242 | + * (wallclock) that represents the time when the data corresponding to the RTP timestamp was | ||
| 243 | + * sampled. The reference clock is shared by all media to be synchronized. The timestamp | ||
| 244 | + * pairs are not transmitted in every data packet, but at a lower rate in RTCP SR packets as | ||
| 245 | + * described in Section 6.4. | ||
| 246 | + * | ||
| 247 | + * The sampling instant is chosen as the point of reference for the RTP timestamp because it is | ||
| 248 | + * known to the transmitting endpoint and has a common denition for all media, independent | ||
| 249 | + * of encoding delays or other processing. The purpose is to allow synchronized presentation of | ||
| 250 | + * all media sampled at the same time. | ||
| 251 | + * | ||
| 252 | + * Applications transmitting stored data rather than data sampled in real time typically use a | ||
| 253 | + * virtual presentation timeline derived from wallclock time to determine when the next frame | ||
| 254 | + * or other unit of each medium in the stored data should be presented. In this case, the RTP | ||
| 255 | + * timestamp would reflect the presentation time for each unit. That is, the RTP timestamp for | ||
| 256 | + * each unit would be related to the wallclock time at which the unit becomes current on the | ||
| 257 | + * virtual presentation timeline. Actual presentation occurs some time later as determined by | ||
| 258 | + * the receiver. | ||
| 259 | + * | ||
| 260 | + * An example describing live audio narration of prerecorded video illustrates the signicance | ||
| 261 | + * of choosing the sampling instant as the reference point. In this scenario, the video would | ||
| 262 | + * be presented locally for the narrator to view and would be simultaneously transmitted using | ||
| 263 | + * RTP. The \sampling instant" of a video frame transmitted in RTP would be established by | ||
| 264 | + * referencing its timestamp to the wallclock time when that video frame was presented to the | ||
| 265 | + * narrator. The sampling instant for the audio RTP packets containing the narrator's speech | ||
| 266 | + * would be established by referencing the same wallclock time when the audio was sampled. | ||
| 267 | + * The audio and video may even be transmitted by dierent hosts if the reference clocks on | ||
| 268 | + * the two hosts are synchronized by some means such as NTP. A receiver can then synchronize | ||
| 269 | + * presentation of the audio and video packets by relating their RTP timestamps using the | ||
| 270 | + * timestamp pairs in RTCP SR packets. | ||
| 271 | + */ | ||
| 272 | + u_int32_t timestamp; //32bits | ||
| 273 | + /** | ||
| 274 | + * SSRC: 32 bits | ||
| 275 | + * The SSRC eld identies the synchronization source. This identier should be chosen | ||
| 276 | + * randomly, with the intent that no two synchronization sources within the same RTP session | ||
| 277 | + * will have the same SSRC identier. An example algorithm for generating a random identier | ||
| 278 | + * is presented in Appendix A.6. Although the probability of multiple sources choosing the same | ||
| 279 | + * identier is low, all RTP implementations must be prepared to detect and resolve collisions. | ||
| 280 | + * Section 8 describes the probability of collision along with a mechanism for resolving collisions | ||
| 281 | + * and detecting RTP-level forwarding loops based on the uniqueness of the SSRC identier. If | ||
| 282 | + * a source changes its source transport address, it must also choose a new SSRC identier to | ||
| 283 | + * avoid being interpreted as a looped source (see Section 8.2). | ||
| 284 | + */ | ||
| 285 | + u_int32_t ssrc; //32bits | ||
| 286 | + | ||
| 287 | + // the payload. | ||
| 288 | + SrsSimpleBuffer* payload; | ||
| 289 | + // whether transport in chunked payload. | ||
| 290 | + bool chunked; | ||
| 291 | + // whether message is completed. | ||
| 292 | + // normal message always completed. | ||
| 293 | + // while chunked completed when the last chunk arriaved. | ||
| 294 | + bool completed; | ||
| 295 | +public: | ||
| 296 | + SrsRtpPacket(); | ||
| 297 | + virtual ~SrsRtpPacket(); | ||
| 298 | +public: | ||
| 299 | + /** | ||
| 300 | + * copy the header from src. | ||
| 301 | + */ | ||
| 302 | + virtual void copy(SrsRtpPacket* src); | ||
| 303 | + /** | ||
| 304 | + * reap the src to this packet, reap the payload. | ||
| 305 | + */ | ||
| 306 | + virtual void reap(SrsRtpPacket* src); | ||
| 307 | + /** | ||
| 308 | + * decode rtp packet from stream. | ||
| 309 | + */ | ||
| 310 | + virtual int decode(SrsStream* stream); | ||
| 311 | +}; | ||
| 312 | + | ||
| 313 | +/** | ||
| 150 | * the sdp in announce, @see rtsp-rfc2326-1998.pdf, page 159 | 314 | * the sdp in announce, @see rtsp-rfc2326-1998.pdf, page 159 |
| 151 | * Appendix C: Use of SDP for RTSP Session Descriptions | 315 | * Appendix C: Use of SDP for RTSP Session Descriptions |
| 152 | * The Session Description Protocol (SDP, RFC 2327 [6]) may be used to | 316 | * The Session Description Protocol (SDP, RFC 2327 [6]) may be used to |
-
请 注册 或 登录 后发表评论