History

avformat/udp: make recv addr of each packet available

Timo Rothenpieler committed 1 year ago

Commit af04a271 parent 2c7e1172 files · +36 −18Browse files

Unified · Split

2 files
  1. libavformat/network.h +2 −0
  2. libavformat/udp.c +34 −18
libavformat/network.h+2−0
@@ -338,4 +338,6 @@ int ff_connect_parallel(struct addrinfo *addrs, int timeout_ms_per_address, · 337 unmodified lines
338 int parallel, URLContext *h, int *fd,338 int parallel, URLContext *h, int *fd,
339 int (*customize_fd)(void *, int, int), void *customize_ctx);339 int (*customize_fd)(void *, int, int), void *customize_ctx);
340 340
341void ff_udp_get_last_recv_addr(URLContext *h, struct sockaddr_storage *addr, socklen_t *addr_len);
342
341#endif /* AVFORMAT_NETWORK_H */343#endif /* AVFORMAT_NETWORK_H */
libavformat/udp.c+34−18
@@ -78,6 +78,12 @@ · 77 unmodified lines
78#define UDP_MAX_PKT_SIZE 6553678#define UDP_MAX_PKT_SIZE 65536
79#define UDP_HEADER_SIZE 879#define UDP_HEADER_SIZE 8
80 80
81typedef struct UDPQueuedPacketHeader {
82 int pkt_size;
83 struct sockaddr_storage addr;
84 socklen_t addr_len;
85} UDPQueuedPacketHeader;
86
81typedef struct UDPContext {87typedef struct UDPContext {
82 const AVClass *class;88 const AVClass *class;
83 int udp_fd;89 int udp_fd;
@@ -107,7 +113,7 @@ typedef struct UDPContext { · 23 unmodified lines
107 pthread_cond_t cond;113 pthread_cond_t cond;
108 int thread_started;114 int thread_started;
109#endif115#endif
110 uint8_t tmp[UDP_MAX_PKT_SIZE+4];116 uint8_t tmp[UDP_MAX_PKT_SIZE + sizeof(UDPQueuedPacketHeader)];
111 int remaining_in_dg;117 int remaining_in_dg;
112 char *localaddr;118 char *localaddr;
113 int timeout;119 int timeout;
@@ -115,6 +121,8 @@ typedef struct UDPContext { · 1 unmodified line
115 char *sources;121 char *sources;
116 char *block;122 char *block;
117 IPSourceFilters filters;123 IPSourceFilters filters;
124 struct sockaddr_storage last_recv_addr;
125 socklen_t last_recv_addr_len;
118} UDPContext;126} UDPContext;
119 127
120#define OFFSET(x) offsetof(UDPContext, x)128#define OFFSET(x) offsetof(UDPContext, x)
@@ -467,6 +475,13 @@ int ff_udp_get_local_port(URLContext *h) · 346 unmodified lines
467 return s->local_port;475 return s->local_port;
468}476}
469 477
478void ff_udp_get_last_recv_addr(URLContext *h, struct sockaddr_storage *addr, socklen_t *addr_len)
479{
480 UDPContext *s = h->priv_data;
481 *addr = s->last_recv_addr;
482 *addr_len = s->last_recv_addr_len;
483}
484
470/**485/**
471 * Return the udp file handle for select() usage to wait for several RTP486 * Return the udp file handle for select() usage to wait for several RTP
472 * streams at the same time.487 * streams at the same time.
@@ -495,30 +510,28 @@ static void *circular_buffer_task_rx( void *_URLContext) · 22 unmodified lines
495 goto end;510 goto end;
496 }511 }
497 while(1) {512 while(1) {
498 int len;513 UDPQueuedPacketHeader pkt_header;
499 struct sockaddr_storage addr;
500 socklen_t addr_len = sizeof(addr);
501 514
502 pthread_mutex_unlock(&s->mutex);515 pthread_mutex_unlock(&s->mutex);
503 /* Blocking operations are always cancellation points;516 /* Blocking operations are always cancellation points;
504 see "General Information" / "Thread Cancelation Overview"517 see "General Information" / "Thread Cancelation Overview"
505 in Single Unix. */518 in Single Unix. */
506 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelstate);519 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelstate);
507 len = recvfrom(s->udp_fd, s->tmp+4, sizeof(s->tmp)-4, 0, (struct sockaddr *)&addr, &addr_len);520 pkt_header.pkt_size = recvfrom(s->udp_fd, s->tmp + sizeof(pkt_header), sizeof(s->tmp) - sizeof(pkt_header), 0, (struct sockaddr *)&pkt_header.addr, &pkt_header.addr_len);
508 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate);521 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate);
509 pthread_mutex_lock(&s->mutex);522 pthread_mutex_lock(&s->mutex);
510 if (len < 0) {523 if (pkt_header.pkt_size < 0) {
511 if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) {524 if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) {
512 s->circular_buffer_error = ff_neterrno();525 s->circular_buffer_error = ff_neterrno();
513 goto end;526 goto end;
514 }527 }
515 continue;528 continue;
516 }529 }
517 if (ff_ip_check_source_lists(&addr, &s->filters))530 if (ff_ip_check_source_lists(&pkt_header.addr, &s->filters))
518 continue;531 continue;
519 AV_WL32(s->tmp, len);532 memcpy(s->tmp, &pkt_header, sizeof(pkt_header));
520 533
521 if (av_fifo_can_write(s->fifo) < len + 4) {534 if (av_fifo_can_write(s->fifo) < pkt_header.pkt_size + sizeof(pkt_header)) {
522 /* No Space left */535 /* No Space left */
523 if (s->overrun_nonfatal) {536 if (s->overrun_nonfatal) {
524 av_log(h, AV_LOG_WARNING, "Circular buffer overrun. "537 av_log(h, AV_LOG_WARNING, "Circular buffer overrun. "
@@ -532,7 +545,7 @@ static void *circular_buffer_task_rx( void *_URLContext) · 7 unmodified lines
532 goto end;545 goto end;
533 }546 }
534 }547 }
535 av_fifo_write(s->fifo, s->tmp, len + 4);548 av_fifo_write(s->fifo, s->tmp, pkt_header.pkt_size + sizeof(pkt_header));
536 pthread_cond_signal(&s->cond);549 pthread_cond_signal(&s->cond);
537 }550 }
538 551
@@ -991,8 +1004,6 @@ static int udp_read(URLContext *h, uint8_t *buf, int size) · 452 unmodified lines
991{1004{
992 UDPContext *s = h->priv_data;1005 UDPContext *s = h->priv_data;
993 int ret;1006 int ret;
994 struct sockaddr_storage addr;
995 socklen_t addr_len = sizeof(addr);
996#if HAVE_PTHREAD_CANCEL1007#if HAVE_PTHREAD_CANCEL
997 int avail, nonblock = h->flags & AVIO_FLAG_NONBLOCK;1008 int avail, nonblock = h->flags & AVIO_FLAG_NONBLOCK;
998 1009
@@ -1001,17 +1012,21 @@ static int udp_read(URLContext *h, uint8_t *buf, int size) · 2 unmodified lines
1001 do {1012 do {
1002 avail = av_fifo_can_read(s->fifo);1013 avail = av_fifo_can_read(s->fifo);
1003 if (avail) { // >=size) {1014 if (avail) { // >=size) {
1004 uint8_t tmp[4];1015 UDPQueuedPacketHeader header;
1016
1017 av_fifo_read(s->fifo, &header, sizeof(header));
1018
1019 s->last_recv_addr = header.addr;
1020 s->last_recv_addr_len = header.addr_len;
1005 1021
1006 av_fifo_read(s->fifo, tmp, 4);1022 avail = header.pkt_size;
1007 avail = AV_RL32(tmp);
1008 if(avail > size){1023 if(avail > size){
1009 av_log(h, AV_LOG_WARNING, "Part of datagram lost due to insufficient buffer size\n");1024 av_log(h, AV_LOG_WARNING, "Part of datagram lost due to insufficient buffer size\n");
1010 avail = size;1025 avail = size;
1011 }1026 }
1012 1027
1013 av_fifo_read(s->fifo, buf, avail);1028 av_fifo_read(s->fifo, buf, avail);
1014 av_fifo_drain2(s->fifo, AV_RL32(tmp) - avail);1029 av_fifo_drain2(s->fifo, header.pkt_size - avail);
1015 pthread_mutex_unlock(&s->mutex);1030 pthread_mutex_unlock(&s->mutex);
1016 return avail;1031 return avail;
1017 } else if(s->circular_buffer_error){1032 } else if(s->circular_buffer_error){
@@ -1043,10 +1058,11 @@ static int udp_read(URLContext *h, uint8_t *buf, int size) · 25 unmodified lines
1043 if (ret < 0)1058 if (ret < 0)
1044 return ret;1059 return ret;
1045 }1060 }
1046 ret = recvfrom(s->udp_fd, buf, size, 0, (struct sockaddr *)&addr, &addr_len);1061 s->last_recv_addr_len = sizeof(s->last_recv_addr);
1062 ret = recvfrom(s->udp_fd, buf, size, 0, (struct sockaddr *)&s->last_recv_addr, &s->last_recv_addr_len);
1047 if (ret < 0)1063 if (ret < 0)
1048 return ff_neterrno();1064 return ff_neterrno();
1049 if (ff_ip_check_source_lists(&addr, &s->filters))1065 if (ff_ip_check_source_lists(&s->last_recv_addr, &s->filters))
1050 return AVERROR(EINTR);1066 return AVERROR(EINTR);
1051 return ret;1067 return ret;
1052}1068}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t