Commit 1bc1cfdd authored by Giancarlo Formicuccia's avatar Giancarlo Formicuccia Committed by Michael Niedermayer

- Gracefully handle the case where not all the streams are requested/wanted

from the client. Simply ignore the unwanted/unasked streams.
- Don't need to pool() for every input character! (the socket is nonblocking,
so the loop is ok).
- Partially resurrect compute_send_delay for avoiding udp flood. Without a
similar patch, udp transmission is seriously unreliable.
(note that we don't link to a specific input reference stream, it's not needed
as the pts values should be coherent anyway. Also, non-monotonic pts
progression is unimportant in the long term).
- rtsp_cmd_pause must reset the time reference
patch by (Giancarlo Formicuccia <ilsensine at inwind dot it>)

Originally committed as revision 2034 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 6bc114b2
...@@ -113,6 +113,7 @@ typedef struct HTTPContext { ...@@ -113,6 +113,7 @@ typedef struct HTTPContext {
AVFormatContext *fmt_in; AVFormatContext *fmt_in;
long start_time; /* In milliseconds - this wraps fairly often */ long start_time; /* In milliseconds - this wraps fairly often */
int64_t first_pts; /* initial pts value */ int64_t first_pts; /* initial pts value */
int64_t cur_pts; /* current pts value */
int pts_stream_index; /* stream we choose as clock reference */ int pts_stream_index; /* stream we choose as clock reference */
/* output format handling */ /* output format handling */
struct FFStream *stream; struct FFStream *stream;
...@@ -786,6 +787,7 @@ static int handle_connection(HTTPContext *c) ...@@ -786,6 +787,7 @@ static int handle_connection(HTTPContext *c)
if (!(c->poll_entry->revents & POLLIN)) if (!(c->poll_entry->revents & POLLIN))
return 0; return 0;
/* read the data */ /* read the data */
read_loop:
len = read(c->fd, c->buffer_ptr, 1); len = read(c->fd, c->buffer_ptr, 1);
if (len < 0) { if (len < 0) {
if (errno != EAGAIN && errno != EINTR) if (errno != EAGAIN && errno != EINTR)
...@@ -810,7 +812,7 @@ static int handle_connection(HTTPContext *c) ...@@ -810,7 +812,7 @@ static int handle_connection(HTTPContext *c)
} else if (ptr >= c->buffer_end) { } else if (ptr >= c->buffer_end) {
/* request too long: cannot do anything */ /* request too long: cannot do anything */
return -1; return -1;
} } else goto read_loop;
} }
break; break;
...@@ -2078,11 +2080,20 @@ static int av_read_frame(AVFormatContext *s, AVPacket *pkt) ...@@ -2078,11 +2080,20 @@ static int av_read_frame(AVFormatContext *s, AVPacket *pkt)
static int compute_send_delay(HTTPContext *c) static int compute_send_delay(HTTPContext *c)
{ {
int datarate = 8 * get_longterm_datarate(&c->datarate, c->data_count); int datarate = 8 * get_longterm_datarate(&c->datarate, c->data_count);
int64_t delta_pts;
int64_t time_pts;
int m_delay;
if (datarate > c->stream->bandwidth * 2000) { if (datarate > c->stream->bandwidth * 2000) {
return 1000; return 1000;
} }
return 0; if(!c->stream->feed && c->first_pts!=AV_NOPTS_VALUE) {
time_pts = ((int64_t)(cur_time - c->start_time) * c->fmt_in->pts_den) /
((int64_t) c->fmt_in->pts_num*1000);
delta_pts = c->cur_pts - time_pts;
m_delay = (delta_pts * 1000 * c->fmt_in->pts_num) / c->fmt_in->pts_den;
return m_delay>0 ? m_delay : 0;
} else return 0;
} }
#endif #endif
...@@ -2189,9 +2200,11 @@ static int http_prepare_data(HTTPContext *c) ...@@ -2189,9 +2200,11 @@ static int http_prepare_data(HTTPContext *c)
} }
} else { } else {
/* update first pts if needed */ /* update first pts if needed */
if (c->first_pts == AV_NOPTS_VALUE) if (c->first_pts == AV_NOPTS_VALUE) {
c->first_pts = pkt.pts; c->first_pts = pkt.pts;
c->start_time = cur_time;
}
c->cur_pts = pkt.pts;
/* send it to the appropriate stream */ /* send it to the appropriate stream */
if (c->stream->feed) { if (c->stream->feed) {
/* if coming from a feed, select the right stream */ /* if coming from a feed, select the right stream */
...@@ -2239,7 +2252,7 @@ static int http_prepare_data(HTTPContext *c) ...@@ -2239,7 +2252,7 @@ static int http_prepare_data(HTTPContext *c)
ctx = c->rtp_ctx[c->packet_stream_index]; ctx = c->rtp_ctx[c->packet_stream_index];
if(!ctx) { if(!ctx) {
av_free_packet(&pkt); av_free_packet(&pkt);
return -1; break;
} }
codec = &ctx->streams[0]->codec; codec = &ctx->streams[0]->codec;
/* only one stream per RTP connection */ /* only one stream per RTP connection */
...@@ -3044,7 +3057,7 @@ static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h) ...@@ -3044,7 +3057,7 @@ static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h)
} }
rtp_c->state = HTTPSTATE_READY; rtp_c->state = HTTPSTATE_READY;
rtp_c->first_pts = AV_NOPTS_VALUE;
/* now everything is OK, so we can send the connection parameters */ /* now everything is OK, so we can send the connection parameters */
rtsp_reply_header(c, RTSP_STATUS_OK); rtsp_reply_header(c, RTSP_STATUS_OK);
/* session ID */ /* session ID */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment