Commit 34370c0ffd for ffmpeg

commit 34370c0ffdf019991a180b93f8aa6084671efe8c
Author: Zhao Zhili <quinkblack@foxmail.com>
Date:   Thu Oct 8 01:19:10 2026 +0800

    avformat/udp: use the circular buffer whenever threads are available

    The rx and tx threads no longer use pthread_cancel(), so gate the
    circular buffer on HAVE_THREADS instead of HAVE_PTHREAD_CANCEL. This
    also drops the w32threads override.

    On targets that have threads but no pthread_cancel(), such as Android,
    udp inputs now start a receive thread and allocate the default 7*4096
    by 188 byte fifo, as on other platforms. Set fifo_size=0 to get the
    previous behavior.

    Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>

diff --git a/doc/protocols.texi b/doc/protocols.texi
index 7812d154db..aa3b88fd58 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -2517,6 +2517,7 @@ exclude the source addresses in the multicast subscription.
 @item fifo_size=@var{units}
 Set the UDP receiving circular buffer size, expressed as a number of
 packets with size of 188 bytes. If not specified defaults to 7*4096.
+Set to 0 to disable the receiving circular buffer and its receive thread.

 @item overrun_nonfatal=@var{1|0}
 Survive in case of UDP receiving circular buffer overrun. Default
diff --git a/libavformat/udp.c b/libavformat/udp.c
index e21c3cd911..a21b04e89c 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -60,12 +60,7 @@
 #define IPPROTO_UDPLITE                                  136
 #endif

-#if HAVE_W32THREADS
-#undef HAVE_PTHREAD_CANCEL
-#define HAVE_PTHREAD_CANCEL 1
-#endif
-
-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
 #include "libavutil/thread.h"
 #endif

@@ -109,7 +104,7 @@ typedef struct UDPContext {
     int64_t bitrate; /* number of bits to send per second */
     int64_t burst_bits;
     int close_req;
-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
     pthread_t circular_buffer_thread;
     pthread_mutex_t mutex;
     pthread_cond_t cond;
@@ -146,7 +141,7 @@ static const AVOption options[] = {
     { "ttl",            "Time to live (multicast only)",                   OFFSET(ttl),            AV_OPT_TYPE_INT,    { .i64 = 16 },     0, 255,     E },
     { "dscp",           "DSCP class for outgoing packets",                 OFFSET(dscp),           AV_OPT_TYPE_INT,    { .i64 = -1 },    -1, 63,      E },
     { "connect",        "set if connect() should be called on socket",     OFFSET(is_connected),   AV_OPT_TYPE_BOOL,   { .i64 =  0 },     0, 1,       .flags = D|E },
-    { "fifo_size",      "set the UDP circular buffer size (in 188-byte packets)", OFFSET(circular_buffer_size), AV_OPT_TYPE_INT, {.i64 = HAVE_PTHREAD_CANCEL ? 7*4096 : 0}, 0, INT_MAX, D },
+    { "fifo_size",      "set the UDP circular buffer size (in 188-byte packets)", OFFSET(circular_buffer_size), AV_OPT_TYPE_INT, {.i64 = HAVE_THREADS ? 7*4096 : 0}, 0, INT_MAX, D },
     { "overrun_nonfatal", "survive in case of UDP receiving circular buffer overrun", OFFSET(overrun_nonfatal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1,    D },
     { "timeout",        "set raise error timeout, in microseconds (only in read mode)",OFFSET(timeout),         AV_OPT_TYPE_INT,  {.i64 = 0}, 0, INT_MAX, D },
     { "sources",        "Source list",                                     OFFSET(sources),        AV_OPT_TYPE_STRING, { .str = NULL },               .flags = D|E },
@@ -525,7 +520,7 @@ static int udp_get_file_handle(URLContext *h)
     return s->udp_fd;
 }

-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
 static void *circular_buffer_task_rx( void *_URLContext)
 {
     URLContext *h = _URLContext;
@@ -712,14 +707,14 @@ static int udp_open(URLContext *h, const char *uri, int flags)
         if (ret < 0)
             goto fail;
     }
-    if (!HAVE_PTHREAD_CANCEL) {
+    if (!HAVE_THREADS) {
         int64_t      optvals[] = {s->overrun_nonfatal, s->bitrate, s->circular_buffer_size};
         const char* optnames[] = {  "overrun_nonfatal",  "bitrate",  "fifo_size"};
         for (unsigned i = 0; i < FF_ARRAY_ELEMS(optvals); i++) {
             if (optvals[i])
                 av_log(h, AV_LOG_WARNING,
                        "'%s' option was set but it is not supported "
-                       "on this build (pthread support is required)\n", optnames[i]);
+                       "on this build (threading support is required)\n", optnames[i]);
         }
     }
     if (s->sources) {
@@ -904,7 +899,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)

     s->udp_fd = udp_fd;

-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
     /*
       Create thread in case of:
       1. Input and circular_buffer_size is set
@@ -950,7 +945,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)
 #endif

     return 0;
-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
  thread_fail:
     pthread_cond_destroy(&s->cond);
  cond_fail:
@@ -979,7 +974,7 @@ static int udp_read(URLContext *h, uint8_t *buf, int size)
 {
     UDPContext *s = h->priv_data;
     int ret;
-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
     int avail, nonblock = h->flags & AVIO_FLAG_NONBLOCK;

     if (s->rx_fifo) {
@@ -1047,7 +1042,7 @@ static int udp_write(URLContext *h, const uint8_t *buf, int size)
     UDPContext *s = h->priv_data;
     int ret;

-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
     if (s->tx_fifo) {
         uint8_t tmp[4];

@@ -1096,7 +1091,7 @@ static int udp_close(URLContext *h)
 {
     UDPContext *s = h->priv_data;

-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
     if (s->thread_started) {
         pthread_mutex_lock(&s->mutex);
         s->close_req = 1;
@@ -1108,7 +1103,7 @@ static int udp_close(URLContext *h)
     if (s->is_multicast && (h->flags & AVIO_FLAG_READ))
         udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr,
                                   (struct sockaddr *)&s->local_addr_storage, h);
-#if HAVE_PTHREAD_CANCEL
+#if HAVE_THREADS
     if (s->thread_started) {
         int ret;
         ret = pthread_join(s->circular_buffer_thread, NULL);