Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
胡斌
/
srs
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
winlin
2015-02-18 11:49:42 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
0cc693a3b81fd7e097578a6552873ac48c5b4192
0cc693a3
1 parent
6a641649
for #133, decode the h264 NALU from rtp.
隐藏空白字符变更
内嵌
并排对比
正在显示
5 个修改的文件
包含
349 行增加
和
4 行删除
trunk/src/app/srs_app_rtsp.cpp
trunk/src/app/srs_app_rtsp.hpp
trunk/src/kernel/srs_kernel_error.hpp
trunk/src/protocol/srs_rtsp_stack.cpp
trunk/src/protocol/srs_rtsp_stack.hpp
trunk/src/app/srs_app_rtsp.cpp
查看文件 @
0cc693a
...
...
@@ -33,19 +33,24 @@ using namespace std;
#include <srs_kernel_log.hpp>
#include <srs_app_utility.hpp>
#include <srs_core_autofree.hpp>
#include <srs_kernel_stream.hpp>
#include <srs_kernel_buffer.hpp>
#ifdef SRS_AUTO_STREAM_CASTER
SrsRtpConn
::
SrsRtpConn
(
SrsRtspConn
*
r
,
int
p
)
SrsRtpConn
::
SrsRtpConn
(
SrsRtspConn
*
r
,
int
p
,
int
sid
)
{
rtsp
=
r
;
_port
=
p
;
stream_id
=
sid
;
listener
=
new
SrsUdpListener
(
this
,
p
);
cache
=
new
SrsRtpPacket
();
}
SrsRtpConn
::~
SrsRtpConn
()
{
srs_freep
(
listener
);
srs_freep
(
cache
);
}
int
SrsRtpConn
::
port
()
...
...
@@ -61,6 +66,53 @@ int SrsRtpConn::listen()
int
SrsRtpConn
::
on_udp_packet
(
sockaddr_in
*
from
,
char
*
buf
,
int
nb_buf
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
true
)
{
SrsStream
stream
;
if
((
ret
=
stream
.
initialize
(
buf
,
nb_buf
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
SrsRtpPacket
pkt
;
if
((
ret
=
pkt
.
decode
(
&
stream
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"rtsp: decode rtp packet failed. ret=%d"
,
ret
);
return
ret
;
}
if
(
pkt
.
chunked
)
{
if
(
!
cache
)
{
cache
=
new
SrsRtpPacket
();
}
cache
->
copy
(
&
pkt
);
cache
->
payload
->
append
(
pkt
.
payload
->
bytes
(),
pkt
.
payload
->
length
());
if
(
!
cache
->
completed
)
{
srs_trace
(
"rtsp: rtp chunked %dB, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB"
,
nb_buf
,
cache
->
version
,
cache
->
payload_type
,
cache
->
sequence_number
,
cache
->
timestamp
,
cache
->
ssrc
,
cache
->
payload
->
length
()
);
return
ret
;
}
}
else
{
srs_freep
(
cache
);
cache
=
new
SrsRtpPacket
();
cache
->
reap
(
&
pkt
);
}
}
srs_trace
(
"rtsp: rtp %dB, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB, chunked=%d"
,
nb_buf
,
cache
->
version
,
cache
->
payload_type
,
cache
->
sequence_number
,
cache
->
timestamp
,
cache
->
ssrc
,
cache
->
payload
->
length
(),
cache
->
chunked
);
// always free it.
SrsAutoFree
(
SrsRtpPacket
,
cache
);
if
((
ret
=
rtsp
->
on_rtp_packet
(
cache
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"rtsp: process rtp packet failed. ret=%d"
,
ret
);
return
ret
;
}
return
ret
;
}
...
...
@@ -162,10 +214,10 @@ int SrsRtspConn::do_cycle()
SrsRtpConn
*
rtp
=
NULL
;
if
(
req
->
stream_id
==
video_id
)
{
srs_freep
(
video_rtp
);
rtp
=
video_rtp
=
new
SrsRtpConn
(
this
,
lpm
);
rtp
=
video_rtp
=
new
SrsRtpConn
(
this
,
lpm
,
video_id
);
}
else
{
srs_freep
(
audio_rtp
);
rtp
=
audio_rtp
=
new
SrsRtpConn
(
this
,
lpm
);
rtp
=
audio_rtp
=
new
SrsRtpConn
(
this
,
lpm
,
audio_id
);
}
if
((
ret
=
rtp
->
listen
())
!=
ERROR_SUCCESS
)
{
srs_error
(
"rtsp: rtp listen at port=%d failed. ret=%d"
,
lpm
,
ret
);
...
...
@@ -210,6 +262,12 @@ int SrsRtspConn::do_cycle()
return
ret
;
}
int
SrsRtspConn
::
on_rtp_packet
(
SrsRtpPacket
*
pkt
)
{
int
ret
=
ERROR_SUCCESS
;
return
ret
;
}
int
SrsRtspConn
::
cycle
()
{
// serve the rtsp client.
...
...
trunk/src/app/srs_app_rtsp.hpp
查看文件 @
0cc693a
...
...
@@ -45,6 +45,7 @@ class SrsRtspConn;
class
SrsRtspStack
;
class
SrsRtspCaster
;
class
SrsConfDirective
;
class
SrsRtpPacket
;
/**
* a rtp connection which transport a stream.
...
...
@@ -54,9 +55,11 @@ class SrsRtpConn: public ISrsUdpHandler
private
:
SrsUdpListener
*
listener
;
SrsRtspConn
*
rtsp
;
SrsRtpPacket
*
cache
;
int
stream_id
;
int
_port
;
public
:
SrsRtpConn
(
SrsRtspConn
*
r
,
int
p
);
SrsRtpConn
(
SrsRtspConn
*
r
,
int
p
,
int
sid
);
virtual
~
SrsRtpConn
();
public
:
virtual
int
port
();
...
...
@@ -103,6 +106,9 @@ public:
virtual
int
serve
();
private
:
virtual
int
do_cycle
();
// internal methods
public:
virtual
int
on_rtp_packet
(
SrsRtpPacket
*
pkt
);
// interface ISrsThreadHandler
public:
virtual
int
cycle
();
...
...
trunk/src/kernel/srs_kernel_error.hpp
查看文件 @
0cc693a
...
...
@@ -144,6 +144,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_RTMP_MIC_CACHE_OVERFLOW 2041
#define ERROR_RTSP_TOKEN_NOT_NORMAL 2042
#define ERROR_RTSP_REQUEST_HEADER_EOF 2043
#define ERROR_RTP_HEADER_CORRUPT 2044
//
// system control message,
// not an error, but special control logic.
...
...
trunk/src/protocol/srs_rtsp_stack.cpp
查看文件 @
0cc693a
...
...
@@ -34,6 +34,7 @@ using namespace std;
#include <srs_kernel_consts.hpp>
#include <srs_core_autofree.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_kernel_stream.hpp>
#ifdef SRS_AUTO_STREAM_CASTER
...
...
@@ -118,6 +119,121 @@ std::string srs_generate_rtsp_method_str(SrsRtspMethod method)
}
}
SrsRtpPacket
::
SrsRtpPacket
()
{
version
=
2
;
padding
=
0
;
extension
=
0
;
csrc_count
=
0
;
marker
=
1
;
payload_type
=
0
;
sequence_number
=
0
;
timestamp
=
0
;
ssrc
=
0
;
payload
=
new
SrsSimpleBuffer
();
chunked
=
false
;
completed
=
false
;
}
SrsRtpPacket
::~
SrsRtpPacket
()
{
srs_freep
(
payload
);
}
void
SrsRtpPacket
::
copy
(
SrsRtpPacket
*
src
)
{
version
=
src
->
version
;
padding
=
src
->
padding
;
extension
=
src
->
extension
;
csrc_count
=
src
->
csrc_count
;
marker
=
src
->
marker
;
payload_type
=
src
->
payload_type
;
sequence_number
=
src
->
sequence_number
;
timestamp
=
src
->
timestamp
;
ssrc
=
src
->
ssrc
;
chunked
=
src
->
chunked
;
completed
=
src
->
completed
;
}
void
SrsRtpPacket
::
reap
(
SrsRtpPacket
*
src
)
{
copy
(
src
);
payload
=
src
->
payload
;
src
->
payload
=
NULL
;
}
int
SrsRtpPacket
::
decode
(
SrsStream
*
stream
)
{
int
ret
=
ERROR_SUCCESS
;
// 12bytes header, atleast 2bytes content.
if
(
!
stream
->
require
(
14
))
{
ret
=
ERROR_RTP_HEADER_CORRUPT
;
srs_error
(
"rtsp: rtp header corrupt. ret=%d"
,
ret
);
return
ret
;
}
int8_t
vv
=
stream
->
read_1bytes
();
version
=
(
vv
>>
6
)
&
0x03
;
padding
=
(
vv
>>
5
)
&
0x01
;
extension
=
(
vv
>>
4
)
&
0x01
;
csrc_count
=
vv
&
0x0f
;
int8_t
mv
=
stream
->
read_1bytes
();
marker
=
(
mv
>>
7
)
&
0x01
;
payload_type
=
mv
&
0x7f
;
sequence_number
=
stream
->
read_2bytes
();
timestamp
=
stream
->
read_4bytes
();
ssrc
=
stream
->
read_4bytes
();
// frame type
// 0... .... reserverd
// .11. .... NALU[0]&0x60
// ...1 11.. FU indicator
// .... ..00 reserverd
int8_t
ftv
=
stream
->
read_1bytes
();
int8_t
nalu_0x60
=
ftv
&
0x60
;
int8_t
fu_indicator
=
ftv
&
0x1c
;
// nri, whatever
// 10.. .... first chunk.
// 00.. .... continous chunk.
// 01.. .... last chunk.
// ...1 1111 NALU[0]&0x1f
int8_t
nriv
=
stream
->
read_1bytes
();
bool
first_chunk
=
(
nriv
&
0xC0
)
==
0x80
;
bool
last_chunk
=
(
nriv
&
0xC0
)
==
0x40
;
bool
contious_chunk
=
(
nriv
&
0xC0
)
==
0x00
;
int8_t
nalu_0x1f
=
nriv
&
0x1f
;
// chunked, generate the first byte NALU.
if
(
fu_indicator
==
0x1c
&&
(
first_chunk
||
last_chunk
||
contious_chunk
))
{
chunked
=
true
;
completed
=
last_chunk
;
// generate and append the first byte NALU.
if
(
first_chunk
)
{
int8_t
nalu_byte0
=
nalu_0x60
|
nalu_0x1f
;
payload
->
append
((
char
*
)
&
nalu_byte0
,
1
);
}
payload
->
append
(
stream
->
data
()
+
stream
->
pos
(),
stream
->
size
()
-
stream
->
pos
());
return
ret
;
}
// no chunked, append to payload.
stream
->
skip
(
-
2
);
payload
->
append
(
stream
->
data
()
+
stream
->
pos
(),
stream
->
size
()
-
stream
->
pos
());
completed
=
true
;
return
ret
;
}
SrsRtspSdp
::
SrsRtspSdp
()
{
state
=
SrsRtspSdpStateOthers
;
...
...
trunk/src/protocol/srs_rtsp_stack.hpp
查看文件 @
0cc693a
...
...
@@ -37,6 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef SRS_AUTO_STREAM_CASTER
class
SrsStream
;
class
SrsSimpleBuffer
;
class
ISrsProtocolReaderWriter
;
...
...
@@ -147,6 +148,169 @@ enum SrsRtspTokenState
};
/**
* the rtp packet.
* 5. RTP Data Transfer Protocol, @see rtp-rfc3550-2003.pdf, page 12
*/
class
SrsRtpPacket
{
public
:
/**
* version (V): 2 bits
* This eld identies the version of RTP. The version dened by this specication is two (2).
* (The value 1 is used by the rst draft version of RTP and the value 0 is used by the protocol
* initially implemented in the \vat" audio tool.)
*/
int8_t
version
;
//2bits
/**
* padding (P): 1 bit
* 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 xed block sizes or for carrying several RTP packets in a
* lower-layer protocol data unit.
*/
int8_t
padding
;
//1bit
/**
* extension (X): 1 bit
* If the extension bit is set, the xed header must be followed by exactly one header extension,
* with a format dened in Section 5.3.1.
*/
int8_t
extension
;
//1bit
/**
* CSRC count (CC): 4 bits
* The CSRC count contains the number of CSRC identiers that follow the xed header.
*/
int8_t
csrc_count
;
//4bits
/**
* marker (M): 1 bit
* The interpretation of the marker is dened by a prole. It is intended to allow signicant
* events such as frame boundaries to be marked in the packet stream. A prole may dene
* additional marker bits or specify that there is no marker bit by changing the number of bits
* in the payload type eld (see Section 5.3).
*/
int8_t
marker
;
//1bit
/**
* payload type (PT): 7 bits
* This eld identies the format of the RTP payload and determines its interpretation by the
* application. A prole may specify a default static mapping of payload type codes to payload
* formats. Additional payload type codes may be dened dynamically through non-RTP means
* (see Section 3). A set of default mappings for audio and video is specied in the companion
* RFC 3551 [1]. An RTP source may change the payload type during a session, but this eld
* should not be used for multiplexing separate media streams (see Section 5.2).
* A receiver must ignore packets with payload types that it does not understand.
*/
int8_t
payload_type
;
//7bits
/**
* sequence number: 16 bits
* 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 should be random (unpredictable) to make known-plaintext attacks on
* encryption more dicult, even if the source itself does not encrypt according to the method
* in Section 9.1, because the packets may flow through a translator that does. Techniques for
* choosing unpredictable numbers are discussed in [17].
*/
u_int16_t
sequence_number
;
//16bits
/**
* timestamp: 32 bits
* The timestamp reflects the sampling instant of the rst 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 (see Section 6.4.1). The resolution
* of the clock must be sucient for the desired synchronization accuracy and for measuring
* packet arrival jitter (one tick per video frame is typically not sucient). The clock frequency
* is dependent on the format of data carried as payload and is specied statically in the prole
* or payload format specication that denes the format, or may be specied dynamically for
* payload formats dened 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 xed-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 should be random, as for the sequence number. Several
* consecutive RTP packets will 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.)
*
* RTP timestamps from dierent media streams may advance at dierent rates and usually
* have independent, random osets. Therefore, although these timestamps are sucient to
* reconstruct the timing of a single stream, directly comparing RTP timestamps from dierent
* media is not eective for synchronization. Instead, for each medium the RTP timestamp
* is related to the sampling instant by pairing it with a timestamp from a reference clock
* (wallclock) that represents the time when the data corresponding to the RTP timestamp was
* sampled. The reference clock is shared by all media to be synchronized. The timestamp
* pairs are not transmitted in every data packet, but at a lower rate in RTCP SR packets as
* described in Section 6.4.
*
* The sampling instant is chosen as the point of reference for the RTP timestamp because it is
* known to the transmitting endpoint and has a common denition for all media, independent
* of encoding delays or other processing. The purpose is to allow synchronized presentation of
* all media sampled at the same time.
*
* Applications transmitting stored data rather than data sampled in real time typically use a
* virtual presentation timeline derived from wallclock time to determine when the next frame
* or other unit of each medium in the stored data should be presented. In this case, the RTP
* timestamp would reflect the presentation time for each unit. That is, the RTP timestamp for
* each unit would be related to the wallclock time at which the unit becomes current on the
* virtual presentation timeline. Actual presentation occurs some time later as determined by
* the receiver.
*
* An example describing live audio narration of prerecorded video illustrates the signicance
* of choosing the sampling instant as the reference point. In this scenario, the video would
* be presented locally for the narrator to view and would be simultaneously transmitted using
* RTP. The \sampling instant" of a video frame transmitted in RTP would be established by
* referencing its timestamp to the wallclock time when that video frame was presented to the
* narrator. The sampling instant for the audio RTP packets containing the narrator's speech
* would be established by referencing the same wallclock time when the audio was sampled.
* The audio and video may even be transmitted by dierent hosts if the reference clocks on
* the two hosts are synchronized by some means such as NTP. A receiver can then synchronize
* presentation of the audio and video packets by relating their RTP timestamps using the
* timestamp pairs in RTCP SR packets.
*/
u_int32_t
timestamp
;
//32bits
/**
* SSRC: 32 bits
* The SSRC eld identies the synchronization source. This identier should be chosen
* randomly, with the intent that no two synchronization sources within the same RTP session
* will have the same SSRC identier. An example algorithm for generating a random identier
* is presented in Appendix A.6. Although the probability of multiple sources choosing the same
* identier 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 identier. If
* a source changes its source transport address, it must also choose a new SSRC identier to
* avoid being interpreted as a looped source (see Section 8.2).
*/
u_int32_t
ssrc
;
//32bits
// the payload.
SrsSimpleBuffer
*
payload
;
// whether transport in chunked payload.
bool
chunked
;
// whether message is completed.
// normal message always completed.
// while chunked completed when the last chunk arriaved.
bool
completed
;
public
:
SrsRtpPacket
();
virtual
~
SrsRtpPacket
();
public
:
/**
* copy the header from src.
*/
virtual
void
copy
(
SrsRtpPacket
*
src
);
/**
* reap the src to this packet, reap the payload.
*/
virtual
void
reap
(
SrsRtpPacket
*
src
);
/**
* decode rtp packet from stream.
*/
virtual
int
decode
(
SrsStream
*
stream
);
};
/**
* the sdp in announce, @see rtsp-rfc2326-1998.pdf, page 159
* Appendix C: Use of SDP for RTSP Session Descriptions
* The Session Description Protocol (SDP, RFC 2327 [6]) may be used to
...
...
请
注册
或
登录
后发表评论