static int tcp_write(URLContext *h, uint8_t *buf, int size) { TCPContext *s = h->priv_data; int ret, size1, fd_max, len; fd_set wfds; struct timeval tv; 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)) { len = send(s->fd, buf, size, 0); if (len < 0) { if (ff_neterrno() != FF_NETERROR(EINTR) && ff_neterrno() != FF_NETERROR(EAGAIN)) return AVERROR(errno); continue; } size -= len; buf += len; } else if (ret < 0) { return -1; } } return size1 - size; }
static int udp_read(URLContext *h, uint8_t *buf, int size) { UDPContext *s = h->priv_data; #ifndef CONFIG_IPV6 struct sockaddr_in from; #else struct sockaddr_storage from; #endif socklen_t from_len; int len; for(;;) { from_len = sizeof(from); len = recvfrom (s->udp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() != FF_NETERROR(EAGAIN) && ff_neterrno() != FF_NETERROR(EINTR)) return AVERROR(EIO); } else { break; } } return len; }
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; 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)) { len = recv(s->fd, buf, size, 0); if (len < 0) { if (ff_neterrno() != FF_NETERROR(EINTR) && ff_neterrno() != FF_NETERROR(EAGAIN)) return AVERROR(errno); } else return len; } else if (ret < 0) { return -1; } } }
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; int ret; for(;;) { if (url_interrupt_cb()) return AVERROR(EINTR); ret = poll(&p, 1, 100); if (ret < 0) { if (ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } if (!(ret == 1 && p.revents & POLLIN)) continue; len = recv(s->udp_fd, buf, size, 0); if (len < 0) { if (ff_neterrno() != FF_NETERROR(EAGAIN) && ff_neterrno() != FF_NETERROR(EINTR)) return AVERROR(EIO); } else { break; } } return len; }
static int tcp_write(URLContext *h, const uint8_t *buf, int size) { TCPContext *s = h->priv_data; int ret, size1, len; struct pollfd p = {s->fd, POLLOUT, 0}; size1 = size; while (size > 0) { if (url_interrupt_cb()) return AVERROR(EINTR); 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) && ff_neterrno() != FF_NETERROR(EAGAIN)) return ff_neterrno(); continue; } size -= len; buf += len; } else if (ret < 0) { if (ff_neterrno() == FF_NETERROR(EINTR)) continue; return -1; } } return size1 - size; }
static int udp_read(URLContext *h, uint8_t *buf, int size) { UDPContext *s = h->priv_data; 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); if (ret < 0) return AVERROR(EIO); if (!(ret > 0 && FD_ISSET(s->udp_fd, &rfds))) continue; len = recv(s->udp_fd, buf, size, 0); if (len < 0) { if (ff_neterrno() != FF_NETERROR(EAGAIN) && ff_neterrno() != FF_NETERROR(EINTR)) return AVERROR(EIO); } else { break; } } return len; }
static int udp_write(URLContext *h, uint8_t *buf, int size) { UDPContext *s = h->priv_data; int ret; for(;;) { ret = sendto (s->udp_fd, buf, size, 0, (struct sockaddr *) &s->dest_addr, s->dest_addr_len); if (ret < 0) { if (ff_neterrno() != FF_NETERROR(EINTR) && ff_neterrno() != FF_NETERROR(EAGAIN)) return AVERROR(EIO); } else { break; } } return size; }
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; int tout_cnt=100; //tout_cnt*time_out=10s 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 = 300 * 1000; ret = select(fd_max + 1, &rfds, NULL, NULL, &tv); if (ret > 0 && FD_ISSET(s->fd, &rfds)) { len = recv(s->fd, buf, size, 0); if (len < 0) { av_log(NULL,AV_LOG_INFO,"tcp_read recv failed: len= %d\n",len); if (ff_neterrno() != FF_NETERROR(EINTR) && ff_neterrno() != FF_NETERROR(EAGAIN)) return AVERROR(ff_neterrno()); } else return len; } else if (ret < 0) { av_log(NULL,AV_LOG_INFO,"tcp_read select failed: ret= %d\n",ret); return -1; } else if(ret == 0){ tout_cnt --; av_log(NULL,AV_LOG_INFO, "tcp_read(%d): read timeout,try again\n",tout_cnt); if(tout_cnt == 0) { return AVERROR(EAGAIN); } } } }
static int tcp_wait_fd(int fd, int write) { int ev = write ? POLLOUT : POLLIN; struct pollfd p = { .fd = fd, .events = ev, .revents = 0 }; int ret; ret = poll(&p, 1, 100); return ret < 0 ? ff_neterrno() : p.revents & ev ? 0 : FF_NETERROR(EAGAIN); } static int tcp_read(URLContext *h, uint8_t *buf, int size) { TCPContext *s = h->priv_data; int ret; if (!(h->flags & URL_FLAG_NONBLOCK)) { ret = tcp_wait_fd(s->fd, 0); if (ret < 0) return ret; } ret = recv(s->fd, buf, size, 0); return ret < 0 ? ff_neterrno() : ret; }
void print_error(const char *filename, int err) { switch(err) { case AVERROR_NUMEXPECTED: fprintf(stderr, "%s: Incorrect image filename syntax.\n" "Use '%%d' to specify the image number:\n" " for img1.jpg, img2.jpg, ..., use 'img%%d.jpg';\n" " for img001.jpg, img002.jpg, ..., use 'img%%03d.jpg'.\n", filename); break; case AVERROR_INVALIDDATA: fprintf(stderr, "%s: Error while parsing header\n", filename); break; case AVERROR_NOFMT: fprintf(stderr, "%s: Unknown format\n", filename); break; case AVERROR(EIO): fprintf(stderr, "%s: I/O error occurred\n" "Usually that means that input file is truncated and/or corrupted.\n", filename); break; case AVERROR(ENOMEM): fprintf(stderr, "%s: memory allocation error occurred\n", filename); break; case AVERROR(ENOENT): fprintf(stderr, "%s: no such file or directory\n", filename); break; #if CONFIG_NETWORK case AVERROR(FF_NETERROR(EPROTONOSUPPORT)): fprintf(stderr, "%s: Unsupported network protocol\n", filename); break; #endif default: fprintf(stderr, "%s: Error while opening file\n", filename); break; } }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct sockaddr_in dest_addr; int port, fd = -1; TCPContext *s = NULL; fd_set wfds; int fd_max, ret; struct timeval tv; socklen_t optlen; char hostname[1024],proto[1024],path[1024]; if(!ff_network_init()) return AVERROR(EIO); url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) return AVERROR(EINVAL); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(port); if (resolve_host(&dest_addr.sin_addr, hostname) < 0) return AVERROR(EIO); fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) return AVERROR(EIO); ff_socket_nonblock(fd, 1); redo: ret = connect(fd, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (ret < 0) { if (ff_neterrno() == FF_NETERROR(EINTR)) goto redo; if (ff_neterrno() != FF_NETERROR(EINPROGRESS) && ff_neterrno() != FF_NETERROR(EAGAIN)) goto fail; /* wait until we are connected or until abort */ for(;;) { if (url_interrupt_cb()) { ret = AVERROR(EINTR); goto fail1; } fd_max = fd; FD_ZERO(&wfds); FD_SET(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(fd, &wfds)) break; } /* test error */ optlen = sizeof(ret); getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); if (ret != 0) goto fail; } s = av_malloc(sizeof(TCPContext)); if (!s) return AVERROR(ENOMEM); h->priv_data = s; h->is_streamed = 1; s->fd = fd; return 0; fail: ret = AVERROR(EIO); fail1: if (fd >= 0) closesocket(fd); return ret; }
/* return non zero if error */ 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; int fd_max, ret; struct timeval tv; socklen_t optlen; char hostname[1024],proto[1024],path[1024]; char portstr[10]; ff_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) return AVERROR(EINVAL); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); if (getaddrinfo(hostname, portstr, &hints, &ai)) return AVERROR(EIO); cur_ai = ai; restart: fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) goto fail; ff_socket_nonblock(fd, 1); redo: ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); if (ret < 0) { if (ff_neterrno() == FF_NETERROR(EINTR)) goto redo; if (ff_neterrno() != FF_NETERROR(EINPROGRESS) && ff_neterrno() != FF_NETERROR(EAGAIN)) goto fail; /* wait until we are connected or until abort */ for(;;) { if (url_interrupt_cb()) { ret = AVERROR(EINTR); goto fail1; } fd_max = fd; FD_ZERO(&wfds); FD_SET(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(fd, &wfds)) break; } /* test error */ optlen = sizeof(ret); getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); if (ret != 0) goto fail; } s = av_malloc(sizeof(TCPContext)); if (!s) { freeaddrinfo(ai); return AVERROR(ENOMEM); } h->priv_data = s; h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: if (cur_ai->ai_next) { /* Retry with the next sockaddr */ cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); goto restart; } ret = AVERROR(EIO); fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) { RTSPState *rt = s->priv_data; int ret; RTSPMessageHeader reply1, *reply = &reply1; char cmd[1024]; retry: if (rt->server_type == RTSP_SERVER_REAL) { int i; for (i = 0; i < s->nb_streams; i++) rt->real_setup[i] = s->streams[i]->discard; if (!rt->need_subscription) { if (memcmp (rt->real_setup, rt->real_setup_cache, sizeof(enum AVDiscard) * s->nb_streams)) { snprintf(cmd, sizeof(cmd), "Unsubscribe: %s\r\n", rt->last_subscription); ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; rt->need_subscription = 1; } } if (rt->need_subscription) { int r, rule_nr, first = 1; memcpy(rt->real_setup_cache, rt->real_setup, sizeof(enum AVDiscard) * s->nb_streams); rt->last_subscription[0] = 0; snprintf(cmd, sizeof(cmd), "Subscribe: "); for (i = 0; i < rt->nb_rtsp_streams; i++) { rule_nr = 0; for (r = 0; r < s->nb_streams; r++) { if (s->streams[r]->priv_data == rt->rtsp_streams[i]) { if (s->streams[r]->discard != AVDISCARD_ALL) { if (!first) av_strlcat(rt->last_subscription, ",", sizeof(rt->last_subscription)); ff_rdt_subscribe_rule( rt->last_subscription, sizeof(rt->last_subscription), i, rule_nr); first = 0; } rule_nr++; } } } av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription); ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; rt->need_subscription = 0; if (rt->state == RTSP_STATE_STREAMING) rtsp_read_play (s); } } ret = ff_rtsp_fetch_packet(s, pkt); 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; } rt->packets++; /* send dummy request to keep TCP connection alive */ if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { if (rt->server_type == RTSP_SERVER_WMS) { ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); } else { ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); } } return 0; }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints, *ai, *cur_ai; int port, fd = -1; TCPContext *s = NULL; int ret; socklen_t optlen; char hostname[1024],proto[1024],path[1024]; char portstr[10]; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) return AVERROR(EINVAL); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { av_log(NULL, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } cur_ai = ai; restart: fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) goto fail; ff_socket_nonblock(fd, 1); 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; goto redo; } if (ff_neterrno() != FF_NETERROR(EINPROGRESS) && ff_neterrno() != FF_NETERROR(EAGAIN)) goto fail; /* wait until we are connected or until abort */ for(;;) { if (url_interrupt_cb()) { ret = AVERROR(EINTR); goto fail1; } ret = poll(&p, 1, 100); if (ret > 0) break; } /* test error */ optlen = sizeof(ret); getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); if (ret != 0) { av_log(NULL, AV_LOG_ERROR, "TCP connection to %s:%d failed: %s\n", hostname, port, strerror(ret)); goto fail; } } s = av_malloc(sizeof(TCPContext)); if (!s) { freeaddrinfo(ai); return AVERROR(ENOMEM); } h->priv_data = s; h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: if (cur_ai->ai_next) { /* Retry with the next sockaddr */ cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); goto restart; } ret = AVERROR(EIO); fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }
static int rtsp_read_header(AVFormatContext *s, AVFormatParameters *ap) { RTSPState *rt = s->priv_data; char host[1024], path[1024], tcpname[1024], cmd[2048], *option_list, *option; URLContext *rtsp_hd; int port, ret, err; RTSPHeader reply1, *reply = &reply1; unsigned char *content = NULL; int protocol_mask = 0; /* extract hostname and port */ url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, path, sizeof(path), s->filename); if (port < 0) port = RTSP_DEFAULT_PORT; /* search for options */ option_list = strchr(path, '?'); if (option_list) { /* remove the options from the path */ *option_list++ = 0; while(option_list) { /* move the option pointer */ option = option_list; option_list = strchr(option_list, '&'); if (option_list) *(option_list++) = 0; /* handle the options */ if (strcmp(option, "udp") == 0) protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP); else if (strcmp(option, "multicast") == 0) protocol_mask = (1<< RTSP_PROTOCOL_RTP_UDP_MULTICAST); else if (strcmp(option, "tcp") == 0) protocol_mask = (1<< RTSP_PROTOCOL_RTP_TCP); } } if (!protocol_mask) protocol_mask = (1 << RTSP_PROTOCOL_RTP_LAST) - 1; /* open the tcp connexion */ snprintf(tcpname, sizeof(tcpname), "tcp://%s:%d", host, port); if (url_open(&rtsp_hd, tcpname, URL_RDWR) < 0) return AVERROR(EIO); rt->rtsp_hd = rtsp_hd; rt->seq = 0; /* describe the stream */ snprintf(cmd, sizeof(cmd), "DESCRIBE %s RTSP/1.0\r\n" "Accept: application/sdp\r\n", s->filename); rtsp_send_cmd(s, cmd, reply, &content); if (!content) { err = AVERROR_INVALIDDATA; goto fail; } if (reply->status_code != RTSP_STATUS_OK) { err = AVERROR_INVALIDDATA; goto fail; } /* now we got the SDP description, we parse it */ ret = sdp_parse(s, (const char *)content); av_freep(&content); if (ret < 0) { err = AVERROR_INVALIDDATA; goto fail; } do { int protocol = ff_log2_tab[protocol_mask & ~(protocol_mask - 1)]; err = make_setup_request(s, host, port, protocol); if (err < 0) goto fail; protocol_mask &= ~(1 << protocol); if (protocol_mask == 0 && err == 1) { err = AVERROR(FF_NETERROR(EPROTONOSUPPORT)); goto fail; } } while (err); rt->state = RTSP_STATE_IDLE; rt->seek_timestamp = 0; /* default is to start stream at position zero */ if (ap->initial_pause) { /* do not start immediately */ } else { if (rtsp_read_play(s) < 0) { err = AVERROR_INVALIDDATA; goto fail; } } return 0; fail: rtsp_close_streams(rt); av_freep(&content); url_close(rt->rtsp_hd); return err; }
static int rtp_read(URLContext *h, uint8_t *buf, int size) { RTPContext *s = h->priv_data; struct sockaddr_in from; socklen_t from_len; int len, fd_max, n; fd_set rfds; struct timeval tv; #if 0 for(;;) { from_len = sizeof(from); len = recvfrom (s->rtp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } break; } #else for(;;) { 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); if (n > 0) { /* first try RTCP */ if (FD_ISSET(s->rtcp_fd, &rfds)) { from_len = sizeof(from); len = recvfrom (s->rtcp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } break; } /* then RTP */ if (FD_ISSET(s->rtp_fd, &rfds)) { from_len = sizeof(from); len = recvfrom (s->rtp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } break; } } else if (n < 0) { if (ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } } #endif return len; }
static int rtp_read(URLContext *h, uint8_t *buf, int size) { RTPContext *s = h->priv_data; struct sockaddr_in from; socklen_t from_len; int len, fd_max, n; fd_set rfds; #if 0 for(;;) { from_len = sizeof(from); len = recvfrom (s->rtp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } break; } #else for(;;) { /* 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) { if (s->rtcp_fd > fd_max) fd_max = s->rtcp_fd; FD_SET(s->rtcp_fd, &rfds); } n = select(fd_max + 1, &rfds, NULL, NULL, NULL); if (n > 0) { /* first try RTCP */ if (FD_ISSET(s->rtcp_fd, &rfds)) { from_len = sizeof(from); len = recvfrom (s->rtcp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } else { /* update remote rtcp address */ char buf[1024]; snprintf(buf, sizeof(buf), "udp://%s:%d", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); udp_set_remote_url(s->rtcp_hd, buf); } break; } /* then RTP */ if (FD_ISSET(s->rtp_fd, &rfds)) { from_len = sizeof(from); len = recvfrom (s->rtp_fd, buf, size, 0, (struct sockaddr *)&from, &from_len); if (len < 0) { if (ff_neterrno() == FF_NETERROR(EAGAIN) || ff_neterrno() == FF_NETERROR(EINTR)) continue; return AVERROR(EIO); } else if (s->rtcp_hd) { /* update remote rtcp address (only if empty) */ typedef struct { int udp_fd; int ttl; int buffer_size; int is_multicast; int local_port; int reuse_socket; #if !CONFIG_IPV6 struct sockaddr_in dest_addr; #else struct sockaddr_storage dest_addr; #endif int dest_addr_len; } UDPContext; URLContext *hd = s->rtcp_hd; UDPContext *h = hd->priv_data; if (h->dest_addr.sin_addr.s_addr == 0) { char buf[1024]; snprintf(buf, sizeof(buf), "udp://%s:%d", inet_ntoa(from.sin_addr), ntohs(from.sin_port)+1); udp_set_remote_url(s->rtcp_hd, buf); } } break; } } } #endif return len; }