[FFmpeg-devel] [PATCH] Replace select with poll

Luca Barbato lu_zero
Fri Jan 28 01:50:41 CET 2011


Select has limitations on the fd values it could accept and silently
breaks when it is reached.
---
 libavformat/os_support.c |    3 --
 libavformat/rtpproto.c   |   24 ++++++-------------
 libavformat/rtsp.c       |   54 ++++++++++++++++++++++++---------------------
 libavformat/rtsp.h       |    5 ++++
 libavformat/rtspenc.c    |   19 +++++-----------
 libavformat/sapdec.c     |   14 ++++-------
 libavformat/tcp.c        |   48 ++++++++++++-----------------------------
 libavformat/udp.c        |   15 ++++--------
 8 files changed, 72 insertions(+), 110 deletions(-)

diff --git a/libavformat/os_support.c b/libavformat/os_support.c
index 83f0820..70cca92 100644
--- a/libavformat/os_support.c
+++ b/libavformat/os_support.c
@@ -236,7 +236,6 @@ int ff_socket_nonblock(int socket, int enable)
 }
 #endif /* CONFIG_NETWORK */
 
-#if CONFIG_FFSERVER
 #if !HAVE_POLL_H
 int poll(struct pollfd *fds, nfds_t numfds, int timeout)
 {
@@ -305,5 +304,3 @@ int poll(struct pollfd *fds, nfds_t numfds, int timeout)
     return rc;
 }
 #endif /* HAVE_POLL_H */
-#endif /* CONFIG_FFSERVER */
-
diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index 6ef6784..59519b9 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -34,8 +34,8 @@
 #include "network.h"
 #include "os_support.h"
 #include <fcntl.h>
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
+#if HAVE_POLL_H
+#include <sys/poll.h>
 #endif
 #include <sys/time.h>
 
@@ -221,9 +221,9 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
     RTPContext *s = h->priv_data;
     struct sockaddr_storage from;
     socklen_t from_len;
-    int len, fd_max, n;
-    fd_set rfds;
-    struct timeval tv;
+    int len, n;
+    struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0},
+                          {s->rtcp_fd, POLLIN, 0} };
 #if 0
     for(;;) {
         from_len = sizeof(from);
@@ -242,18 +242,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
         if (url_interrupt_cb())
             return AVERROR(EINTR);
         /* build fdset to listen to RTP and RTCP packets */
-        FD_ZERO(&rfds);
-        fd_max = s->rtp_fd;
-        FD_SET(s->rtp_fd, &rfds);
-        if (s->rtcp_fd > fd_max)
-            fd_max = s->rtcp_fd;
-        FD_SET(s->rtcp_fd, &rfds);
-        tv.tv_sec = 0;
-        tv.tv_usec = 100 * 1000;
-        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
+        n = poll(p, 2, 100);
         if (n > 0) {
             /* first try RTCP */
-            if (FD_ISSET(s->rtcp_fd, &rfds)) {
+            if (p[1].revents & POLLIN) {
                 from_len = sizeof(from);
                 len = recvfrom (s->rtcp_fd, buf, size, 0,
                                 (struct sockaddr *)&from, &from_len);
@@ -266,7 +258,7 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
                 break;
             }
             /* then RTP */
-            if (FD_ISSET(s->rtp_fd, &rfds)) {
+            if (p[0].revents & POLLIN) {
                 from_len = sizeof(from);
                 len = recvfrom (s->rtp_fd, buf, size, 0,
                                 (struct sockaddr *)&from, &from_len);
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 752f429..e7c0fa5 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -26,8 +26,8 @@
 #include "avformat.h"
 
 #include <sys/time.h>
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
+#if HAVE_POLL_H
+#include <poll.h>
 #endif
 #include <strings.h>
 #include "internal.h"
@@ -44,11 +44,11 @@
 //#define DEBUG
 //#define DEBUG_RTP_TCP
 
-/* Timeout values for socket select, in ms,
+/* Timeout values for socket poll, in ms,
  * and read_packet(), in seconds  */
-#define SELECT_TIMEOUT_MS 100
+#define POLL_TIMEOUT_MS 100
 #define READ_PACKET_TIMEOUT_S 10
-#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS
+#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS
 #define SDP_MAX_SIZE 16384
 #define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
 
@@ -429,8 +429,14 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
     }
 }
 
+/**
+ * Parse the sdp description and allocate the rtp streams and the
+ * pollfd array used for udp ones.
+ */
+
 int ff_sdp_parse(AVFormatContext *s, const char *content)
 {
+    RTSPState *rt = s->priv_data;
     const char *p;
     int letter;
     /* Some SDP lines, particularly for Realmedia or ASF RTSP streams,
@@ -470,6 +476,7 @@ int ff_sdp_parse(AVFormatContext *s, const char *content)
         if (*p == '\n')
             p++;
     }
+    rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1));
     return 0;
 }
 #endif /* CONFIG_RTPDEC */
@@ -531,6 +538,7 @@ void ff_rtsp_close_streams(AVFormatContext *s)
         av_close_input_stream (rt->asf_ctx);
         rt->asf_ctx = NULL;
     }
+    av_free(rt->p);
     av_free(rt->recvbuf);
 }
 
@@ -1554,55 +1562,51 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
 {
     RTSPState *rt = s->priv_data;
     RTSPStream *rtsp_st;
-    fd_set rfds;
-    int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0;
-    struct timeval tv;
+    int n, i, ret, tcp_fd, timeout_cnt = 0;
+    int max_p = 0;
+    struct pollfd *p = rt->p;
 
     for (;;) {
         if (url_interrupt_cb())
             return AVERROR(EINTR);
         if (wait_end && wait_end - av_gettime() < 0)
             return AVERROR(EAGAIN);
-        FD_ZERO(&rfds);
+        max_p = 0;
         if (rt->rtsp_hd) {
-            tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd);
-            FD_SET(tcp_fd, &rfds);
+            tcp_fd = url_get_file_handle(rt->rtsp_hd);
+            p[max_p].fd = tcp_fd;
+            p[max_p++].events = POLLIN;
         } else {
-            fd_max = 0;
             tcp_fd = -1;
         }
         for (i = 0; i < rt->nb_rtsp_streams; i++) {
             rtsp_st = rt->rtsp_streams[i];
             if (rtsp_st->rtp_handle) {
-                fd = url_get_file_handle(rtsp_st->rtp_handle);
-                fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
-                if (FFMAX(fd, fd_rtcp) > fd_max)
-                    fd_max = FFMAX(fd, fd_rtcp);
-                FD_SET(fd, &rfds);
-                FD_SET(fd_rtcp, &rfds);
+                p[max_p].fd = url_get_file_handle(rtsp_st->rtp_handle);
+                p[max_p++].events = POLLIN;
+                p[max_p].fd = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
+                p[max_p++].events = POLLIN;
             }
         }
-        tv.tv_sec = 0;
-        tv.tv_usec = SELECT_TIMEOUT_MS * 1000;
-        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
+        n = poll(p, max_p, POLL_TIMEOUT_MS);
         if (n > 0) {
+            int j = 1 - (tcp_fd == -1);
             timeout_cnt = 0;
             for (i = 0; i < rt->nb_rtsp_streams; i++) {
                 rtsp_st = rt->rtsp_streams[i];
                 if (rtsp_st->rtp_handle) {
-                    fd = url_get_file_handle(rtsp_st->rtp_handle);
-                    fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
-                    if (FD_ISSET(fd_rtcp, &rfds) || FD_ISSET(fd, &rfds)) {
+                    if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) {
                         ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
                         if (ret > 0) {
                             *prtsp_st = rtsp_st;
                             return ret;
                         }
                     }
+                    j+=2;
                 }
             }
 #if CONFIG_RTSP_DEMUXER
-            if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) {
+            if (tcp_fd != -1 && p[0].revents & POLLIN) {
                 RTSPMessageHeader reply;
 
                 ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL);
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index f0ead10..14d3f41 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -326,6 +326,11 @@ typedef struct RTSPState {
      * The number of returned packets
      */
     uint64_t packets;
+
+    /**
+     * Polling array for udp
+     */
+    struct pollfd *p;
 } RTSPState;
 
 /**
diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c
index dc8ecd8..88f093f 100644
--- a/libavformat/rtspenc.c
+++ b/libavformat/rtspenc.c
@@ -22,8 +22,8 @@
 #include "avformat.h"
 
 #include <sys/time.h>
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
+#if HAVE_POLL_H
+#include <poll.h>
 #endif
 #include "network.h"
 #include "rtsp.h"
@@ -172,23 +172,16 @@ static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     RTSPState *rt = s->priv_data;
     RTSPStream *rtsp_st;
-    fd_set rfds;
-    int n, tcp_fd;
-    struct timeval tv;
+    int n;
+    struct pollfd p = {url_get_file_handle(rt->rtsp_hd), POLLIN, 0};
     AVFormatContext *rtpctx;
     int ret;
 
-    tcp_fd = url_get_file_handle(rt->rtsp_hd);
-
     while (1) {
-        FD_ZERO(&rfds);
-        FD_SET(tcp_fd, &rfds);
-        tv.tv_sec = 0;
-        tv.tv_usec = 0;
-        n = select(tcp_fd + 1, &rfds, NULL, NULL, &tv);
+        n = poll(&p, 1, 0);
         if (n <= 0)
             break;
-        if (FD_ISSET(tcp_fd, &rfds)) {
+        if (p.revents & POLLIN) {
             RTSPMessageHeader reply;
 
             /* Don't let ff_rtsp_read_reply handle interleaved packets,
diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c
index 208591c..73525f5 100644
--- a/libavformat/sapdec.c
+++ b/libavformat/sapdec.c
@@ -25,8 +25,8 @@
 #include "network.h"
 #include "os_support.h"
 #include "internal.h"
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
+#if HAVE_POLL_H
+#include <poll.h>
 #endif
 #include <sys/time.h>
 
@@ -183,19 +183,15 @@ static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt)
     struct SAPState *sap = s->priv_data;
     int fd = url_get_file_handle(sap->ann_fd);
     int n, ret;
-    fd_set rfds;
-    struct timeval tv;
+    struct pollfd p = {fd, POLLIN, 0};
     uint8_t recvbuf[1500];
 
     if (sap->eof)
         return AVERROR_EOF;
 
     while (1) {
-        FD_ZERO(&rfds);
-        FD_SET(fd, &rfds);
-        tv.tv_sec = tv.tv_usec = 0;
-        n = select(fd + 1, &rfds, NULL, NULL, &tv);
-        if (n <= 0 || !FD_ISSET(fd, &rfds))
+        n = poll(&p, 1, 0);
+        if (n <= 0 || !(p.revents & POLLIN))
             break;
         ret = url_read(sap->ann_fd, recvbuf, sizeof(recvbuf));
         if (ret >= 8) {
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index 5cb4b8f..ac4e4b0 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -23,8 +23,8 @@
 #include "internal.h"
 #include "network.h"
 #include "os_support.h"
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
+#if HAVE_POLL_H
+#include <poll.h>
 #endif
 #include <sys/time.h>
 
@@ -38,9 +38,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
     struct addrinfo hints, *ai, *cur_ai;
     int port, fd = -1;
     TCPContext *s = NULL;
-    fd_set wfds, efds;
-    int fd_max, ret;
-    struct timeval tv;
+    int ret;
     socklen_t optlen;
     char hostname[1024],proto[1024],path[1024];
     char portstr[10];
@@ -73,6 +71,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
  redo:
     ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
     if (ret < 0) {
+        struct pollfd p = {fd, POLLOUT, 0};
         if (ff_neterrno() == FF_NETERROR(EINTR)) {
             if (url_interrupt_cb())
                 goto fail1;
@@ -88,15 +87,8 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
                 ret = AVERROR(EINTR);
                 goto fail1;
             }
-            fd_max = fd;
-            FD_ZERO(&wfds);
-            FD_ZERO(&efds);
-            FD_SET(fd, &wfds);
-            FD_SET(fd, &efds);
-            tv.tv_sec = 0;
-            tv.tv_usec = 100 * 1000;
-            ret = select(fd_max + 1, NULL, &wfds, &efds, &tv);
-            if (ret > 0 && (FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds)))
+            ret = poll(&p, 1, 100);
+            if (ret > 0)
                 break;
         }
 
@@ -140,20 +132,14 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
 static int tcp_read(URLContext *h, uint8_t *buf, int size)
 {
     TCPContext *s = h->priv_data;
-    int len, fd_max, ret;
-    fd_set rfds;
-    struct timeval tv;
+    struct pollfd p = {s->fd, POLLIN, 0};
+    int len, ret;
 
     for (;;) {
         if (url_interrupt_cb())
             return AVERROR(EINTR);
-        fd_max = s->fd;
-        FD_ZERO(&rfds);
-        FD_SET(s->fd, &rfds);
-        tv.tv_sec = 0;
-        tv.tv_usec = 100 * 1000;
-        ret = select(fd_max + 1, &rfds, NULL, NULL, &tv);
-        if (ret > 0 && FD_ISSET(s->fd, &rfds)) {
+        ret = poll(&p, 1, 100);
+        if (ret == 1 && p.revents & POLLIN) {
             len = recv(s->fd, buf, size, 0);
             if (len < 0) {
                 if (ff_neterrno() != FF_NETERROR(EINTR) &&
@@ -171,21 +157,15 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size)
 static int tcp_write(URLContext *h, const uint8_t *buf, int size)
 {
     TCPContext *s = h->priv_data;
-    int ret, size1, fd_max, len;
-    fd_set wfds;
-    struct timeval tv;
+    int ret, size1, len;
+    struct pollfd p = {s->fd, POLLOUT, 0};
 
     size1 = size;
     while (size > 0) {
         if (url_interrupt_cb())
             return AVERROR(EINTR);
-        fd_max = s->fd;
-        FD_ZERO(&wfds);
-        FD_SET(s->fd, &wfds);
-        tv.tv_sec = 0;
-        tv.tv_usec = 100 * 1000;
-        ret = select(fd_max + 1, NULL, &wfds, NULL, &tv);
-        if (ret > 0 && FD_ISSET(s->fd, &wfds)) {
+        ret = poll(&p, 1, 100);
+        if (ret == 1 && p.revents & POLLOUT) {
             len = send(s->fd, buf, size, 0);
             if (len < 0) {
                 if (ff_neterrno() != FF_NETERROR(EINTR) &&
diff --git a/libavformat/udp.c b/libavformat/udp.c
index 8080c98..aa17c97 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -31,8 +31,8 @@
 #include "internal.h"
 #include "network.h"
 #include "os_support.h"
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
+#if HAVE_POLL_H
+#include <poll.h>
 #endif
 #include <sys/time.h>
 
@@ -432,25 +432,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
 static int udp_read(URLContext *h, uint8_t *buf, int size)
 {
     UDPContext *s = h->priv_data;
+    struct pollfd p = {s->udp_fd, POLLIN, 0};
     int len;
-    fd_set rfds;
     int ret;
-    struct timeval tv;
 
     for(;;) {
         if (url_interrupt_cb())
             return AVERROR(EINTR);
-        FD_ZERO(&rfds);
-        FD_SET(s->udp_fd, &rfds);
-        tv.tv_sec = 0;
-        tv.tv_usec = 100 * 1000;
-        ret = select(s->udp_fd + 1, &rfds, NULL, NULL, &tv);
+        ret = poll(&p, 1, 100);
         if (ret < 0) {
             if (ff_neterrno() == FF_NETERROR(EINTR))
                 continue;
             return AVERROR(EIO);
         }
-        if (!(ret > 0 && FD_ISSET(s->udp_fd, &rfds)))
+        if (!(ret == 1 && p.revents & POLLIN))
             continue;
         len = recv(s->udp_fd, buf, size, 0);
         if (len < 0) {
-- 
1.7.2.2




More information about the ffmpeg-devel mailing list