mirror of https://git.ffmpeg.org/ffmpeg.git
rtspdec: Retry with TCP if UDP failed
Signed-off-by: Janne Grunau <janne-ffmpeg@jannau.net>
(cherry picked from commit 2762a7a28b
)
This commit is contained in:
parent
2afd30bf7a
commit
4f40ec0552
|
@ -1291,7 +1291,7 @@ int ff_rtsp_connect(AVFormatContext *s)
|
||||||
int port, err, tcp_fd;
|
int port, err, tcp_fd;
|
||||||
RTSPMessageHeader reply1 = {0}, *reply = &reply1;
|
RTSPMessageHeader reply1 = {0}, *reply = &reply1;
|
||||||
int lower_transport_mask = 0;
|
int lower_transport_mask = 0;
|
||||||
char real_challenge[64];
|
char real_challenge[64] = "";
|
||||||
struct sockaddr_storage peer;
|
struct sockaddr_storage peer;
|
||||||
socklen_t peer_len = sizeof(peer);
|
socklen_t peer_len = sizeof(peer);
|
||||||
|
|
||||||
|
@ -1515,6 +1515,8 @@ redirect:
|
||||||
}
|
}
|
||||||
} while (err);
|
} while (err);
|
||||||
|
|
||||||
|
rt->lower_transport_mask = lower_transport_mask;
|
||||||
|
av_strlcpy(rt->real_challenge, real_challenge, sizeof(rt->real_challenge));
|
||||||
rt->state = RTSP_STATE_IDLE;
|
rt->state = RTSP_STATE_IDLE;
|
||||||
rt->seek_timestamp = 0; /* default is to start stream at position zero */
|
rt->seek_timestamp = 0; /* default is to start stream at position zero */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -248,6 +248,9 @@ typedef struct RTSPState {
|
||||||
* of RTSPMessageHeader->real_challenge */
|
* of RTSPMessageHeader->real_challenge */
|
||||||
enum RTSPServerType server_type;
|
enum RTSPServerType server_type;
|
||||||
|
|
||||||
|
/** the "RealChallenge1:" field from the server */
|
||||||
|
char real_challenge[64];
|
||||||
|
|
||||||
/** plaintext authorization line (username:password) */
|
/** plaintext authorization line (username:password) */
|
||||||
char auth[128];
|
char auth[128];
|
||||||
|
|
||||||
|
@ -313,6 +316,16 @@ typedef struct RTSPState {
|
||||||
/** Filter incoming UDP packets - receive packets only from the right
|
/** Filter incoming UDP packets - receive packets only from the right
|
||||||
* source address and port. */
|
* source address and port. */
|
||||||
int filter_source;
|
int filter_source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mask with all requested transport methods
|
||||||
|
*/
|
||||||
|
int lower_transport_mask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of returned packets
|
||||||
|
*/
|
||||||
|
uint64_t packets;
|
||||||
} RTSPState;
|
} RTSPState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -229,6 +229,20 @@ found:
|
||||||
*prtsp_st = rtsp_st;
|
*prtsp_st = rtsp_st;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int resetup_tcp(AVFormatContext *s)
|
||||||
|
{
|
||||||
|
RTSPState *rt = s->priv_data;
|
||||||
|
char host[1024];
|
||||||
|
int port;
|
||||||
|
|
||||||
|
av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0,
|
||||||
|
s->filename);
|
||||||
|
ff_rtsp_undo_setup(s);
|
||||||
|
return ff_rtsp_make_setup_request(s, host, port, RTSP_LOWER_TRANSPORT_TCP,
|
||||||
|
rt->real_challenge);
|
||||||
|
}
|
||||||
|
|
||||||
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
|
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||||
{
|
{
|
||||||
RTSPState *rt = s->priv_data;
|
RTSPState *rt = s->priv_data;
|
||||||
|
@ -236,6 +250,7 @@ static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||||
RTSPMessageHeader reply1, *reply = &reply1;
|
RTSPMessageHeader reply1, *reply = &reply1;
|
||||||
char cmd[1024];
|
char cmd[1024];
|
||||||
|
|
||||||
|
retry:
|
||||||
if (rt->server_type == RTSP_SERVER_REAL) {
|
if (rt->server_type == RTSP_SERVER_REAL) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -295,8 +310,32 @@ static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ff_rtsp_fetch_packet(s, pkt);
|
ret = ff_rtsp_fetch_packet(s, pkt);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
if (ret == FF_NETERROR(ETIMEDOUT) && !rt->packets) {
|
||||||
|
if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
|
||||||
|
rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_TCP)) {
|
||||||
|
RTSPMessageHeader reply1, *reply = &reply1;
|
||||||
|
av_log(s, AV_LOG_WARNING, "UDP timeout, retrying with TCP\n");
|
||||||
|
if (rtsp_read_pause(s) != 0)
|
||||||
|
return -1;
|
||||||
|
// TEARDOWN is required on Real-RTSP, but might make
|
||||||
|
// other servers close the connection.
|
||||||
|
if (rt->server_type == RTSP_SERVER_REAL)
|
||||||
|
ff_rtsp_send_cmd(s, "TEARDOWN", rt->control_uri, NULL,
|
||||||
|
reply, NULL);
|
||||||
|
rt->session_id[0] = '\0';
|
||||||
|
if (resetup_tcp(s) == 0) {
|
||||||
|
rt->state = RTSP_STATE_IDLE;
|
||||||
|
rt->need_subscription = 1;
|
||||||
|
if (rtsp_read_play(s) != 0)
|
||||||
|
return -1;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
rt->packets++;
|
||||||
|
|
||||||
/* send dummy request to keep TCP connection alive */
|
/* send dummy request to keep TCP connection alive */
|
||||||
if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
|
if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) {
|
||||||
|
|
Loading…
Reference in New Issue