- Gracefully handle the case where not all the streams are requested/wanted
authorGiancarlo Formicuccia <ilsensine@inwind.it>
Fri, 11 Jul 2003 22:30:12 +0000 (22:30 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 11 Jul 2003 22:30:12 +0000 (22:30 +0000)
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

ffserver.c

index 6cebfb4..a0ded91 100644 (file)
@@ -113,6 +113,7 @@ typedef struct HTTPContext {
     AVFormatContext *fmt_in;
     long start_time;            /* In milliseconds - this wraps fairly often */
     int64_t first_pts;            /* initial pts value */
+    int64_t cur_pts;              /* current pts value */
     int pts_stream_index;       /* stream we choose as clock reference */
     /* output format handling */
     struct FFStream *stream;
@@ -786,6 +787,7 @@ static int handle_connection(HTTPContext *c)
         if (!(c->poll_entry->revents & POLLIN))
             return 0;
         /* read the data */
+    read_loop:
         len = read(c->fd, c->buffer_ptr, 1);
         if (len < 0) {
             if (errno != EAGAIN && errno != EINTR)
@@ -810,7 +812,7 @@ static int handle_connection(HTTPContext *c)
             } else if (ptr >= c->buffer_end) {
                 /* request too long: cannot do anything */
                 return -1;
-            }
+            } else goto read_loop;
         }
         break;
 
@@ -2078,11 +2080,20 @@ static int av_read_frame(AVFormatContext *s, AVPacket *pkt)
 static int compute_send_delay(HTTPContext *c)
 {
     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) {
         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
@@ -2189,9 +2200,11 @@ static int http_prepare_data(HTTPContext *c)
                     }
                 } else {
                     /* 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->start_time = cur_time;
+                    }
+                    c->cur_pts = pkt.pts;
                     /* send it to the appropriate stream */
                     if (c->stream->feed) {
                         /* if coming from a feed, select the right stream */
@@ -2239,7 +2252,7 @@ static int http_prepare_data(HTTPContext *c)
                             ctx = c->rtp_ctx[c->packet_stream_index];
                             if(!ctx) {
                               av_free_packet(&pkt);
-                              return -1;
+                              break;
                             }
                             codec = &ctx->streams[0]->codec;
                             /* only one stream per RTP connection */
@@ -3044,7 +3057,7 @@ static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPHeader *h)
     }
     
     rtp_c->state = HTTPSTATE_READY;
-    
+    rtp_c->first_pts = AV_NOPTS_VALUE;
     /* now everything is OK, so we can send the connection parameters */
     rtsp_reply_header(c, RTSP_STATUS_OK);
     /* session ID */