Skip to content

Commit

Permalink
rtsp: Add listen mode
Browse files Browse the repository at this point in the history
This makes the RTSP demuxer act as a server, listening for an
incoming connection.

Signed-off-by: Martin Storsjö <martin@martin.st>
  • Loading branch information
nenjordi authored and mstorsjo committed Jul 10, 2012
1 parent 6e71c12 commit a8ad6ff
Show file tree
Hide file tree
Showing 7 changed files with 601 additions and 39 deletions.
1 change: 1 addition & 0 deletions Changelog
Expand Up @@ -31,6 +31,7 @@ version <next>:
- join audio filter
- audio channel mapping filter
- Microsoft ATC Screen decoder
- RTSP listen mode


version 0.8:
Expand Down
8 changes: 8 additions & 0 deletions doc/protocols.texi
Expand Up @@ -347,6 +347,8 @@ Flags for @code{rtsp_flags}:
@table @option
@item filter_src
Accept packets only from negotiated peer address and port.
@item listen
Act as a server, listening for an incoming connection.
@end table

When receiving data over UDP, the demuxer tries to reorder received packets
Expand Down Expand Up @@ -379,6 +381,12 @@ To send a stream in realtime to a RTSP server, for others to watch:
avconv -re -i @var{input} -f rtsp -muxdelay 0.1 rtsp://server/live.sdp
@end example

To receive a stream in realtime:

@example
avconv -rtsp_flags listen -i rtsp://ownaddress/live.sdp @var{output}
@end example

@section sap

Session Announcement Protocol (RFC 2974). This is not technically a
Expand Down
30 changes: 21 additions & 9 deletions libavformat/rtsp.c
Expand Up @@ -63,7 +63,8 @@

#define RTSP_FLAG_OPTS(name, longname) \
{ name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \
{ "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }
{ "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }, \
{ "listen", "Wait for incoming connections", 0, AV_OPT_TYPE_CONST, {RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" }

#define RTSP_MEDIATYPE_OPTS(name, longname) \
{ name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \
Expand All @@ -83,6 +84,7 @@ const AVOption ff_rtsp_options[] = {
RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"),
{ "min_port", "Minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC },
{ "max_port", "Maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC },
{ "timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {-1}, INT_MIN, INT_MAX, DEC },
{ NULL },
};

Expand Down Expand Up @@ -1714,14 +1716,24 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
}
#if CONFIG_RTSP_DEMUXER
if (tcp_fd != -1 && p[0].revents & POLLIN) {
RTSPMessageHeader reply;

ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL);
if (ret < 0)
return ret;
/* XXX: parse message */
if (rt->state != RTSP_STATE_STREAMING)
return 0;
if (rt->rtsp_flags & RTSP_FLAG_LISTEN) {
if (rt->state == RTSP_STATE_STREAMING) {
if (!ff_rtsp_parse_streaming_commands(s))
return AVERROR_EOF;
else
av_log(s, AV_LOG_WARNING,
"Unable to answer to TEARDOWN\n");
} else
return 0;
} else {
RTSPMessageHeader reply;
ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL);
if (ret < 0)
return ret;
/* XXX: parse message */
if (rt->state != RTSP_STATE_STREAMING)
return 0;
}
}
#endif
} else if (n == 0 && ++timeout_cnt >= MAX_TIMEOUTS) {
Expand Down
12 changes: 12 additions & 0 deletions libavformat/rtsp.h
Expand Up @@ -372,11 +372,17 @@ typedef struct RTSPState {
* Minimum and maximum local UDP ports.
*/
int rtp_port_min, rtp_port_max;

/**
* Timeout to wait for incoming connections.
*/
int initial_timeout;
} RTSPState;

#define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets -
receive packets only from the right
source address and port. */
#define RTSP_FLAG_LISTEN 0x2 /**< Wait for incoming connections. */

/**
* Describe a single stream, as identified by a single m= line block in the
Expand Down Expand Up @@ -528,6 +534,12 @@ int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply);
*/
int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr);

/**
* Parse RTSP commands (OPTIONS, PAUSE and TEARDOWN) during streaming in
* listen mode.
*/
int ff_rtsp_parse_streaming_commands(AVFormatContext *s);

/**
* Parse an SDP description of streams by populating an RTSPState struct
* within the AVFormatContext; also allocate the RTP streams and the
Expand Down
14 changes: 14 additions & 0 deletions libavformat/rtspcodes.h
Expand Up @@ -37,4 +37,18 @@ RTSP_STATUS_SERVICE =503, /**< Service Unavailable */
RTSP_STATUS_VERSION =505, /**< RTSP Version not supported */
};

enum RTSPMethod {
DESCRIBE,
ANNOUNCE,
OPTIONS,
SETUP,
PLAY,
PAUSE,
TEARDOWN,
GET_PARAMETER,
SET_PARAMETER,
REDIRECT,
RECORD,
UNKNOWN = -1,
};
#endif /* AVFORMAT_RTSPCODES_H */

0 comments on commit a8ad6ff

Please sign in to comment.