| @@ -78,6 +78,12 @@ · 77 unmodified lines |
| 78 | #define UDP_MAX_PKT_SIZE 65536 | 78 | #define UDP_MAX_PKT_SIZE 65536 |
| 79 | #define UDP_HEADER_SIZE 8 | 79 | #define UDP_HEADER_SIZE 8 |
| 80 | | 80 | |
| | 81 | typedef struct UDPQueuedPacketHeader { |
| | 82 | int pkt_size; |
| | 83 | struct sockaddr_storage addr; |
| | 84 | socklen_t addr_len; |
| | 85 | } UDPQueuedPacketHeader; |
| | 86 | |
| 81 | typedef struct UDPContext { | 87 | typedef 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 | #endif | 115 | #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 | |
| | 478 | void 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 RTP | 486 | * 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_CANCEL | 1007 | #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 | } |