1313#include <lwip/netdb.h>
1414#include <string.h>
1515#include <math.h>
16+ #include "esp_rom_sys.h" // For ets_delay_us
1617
1718#define TAG "scream_sender"
1819
@@ -22,6 +23,11 @@ static const char header[] = {1, 16, 2, 0, 0};
2223#define CHUNK_SIZE 1152
2324#define PACKET_SIZE (CHUNK_SIZE + HEADER_SIZE)
2425
26+ // Socket options
27+ #define UDP_TX_BUFFER_SIZE (1024 * 32)
28+ #define UDP_SEND_TIMEOUT_MS 10
29+ #define MAX_SEND_RETRIES 3
30+
2531// State variables
2632static bool s_is_sender_initialized = false;
2733static bool s_is_sender_running = false;
@@ -32,7 +38,7 @@ static struct sockaddr_in s_dest_addr;
3238
3339// Buffer for audio data
3440static char s_data_out [PACKET_SIZE ];
35- static char s_data_in [CHUNK_SIZE * 10 ];
41+ static char s_data_in [CHUNK_SIZE * 16 ]; // Increased buffer size
3642static int s_data_in_head = 0 ;
3743
3844// UAC callbacks
@@ -48,7 +54,27 @@ static esp_err_t uac_device_output_cb(uint8_t *buf, size_t len, void *arg)
4854 // Process the data in chunks
4955 while (s_data_in_head >= CHUNK_SIZE ) {
5056 memcpy (s_data_out + HEADER_SIZE , s_data_in , CHUNK_SIZE );
51- sendto (s_sock , s_data_out , PACKET_SIZE , 0 , (struct sockaddr * )& s_dest_addr , sizeof (s_dest_addr ));
57+
58+ // Send with retry logic
59+ int sent = -1 ;
60+ int retry_count = 0 ;
61+
62+ while (sent < 0 && retry_count < MAX_SEND_RETRIES ) {
63+ sent = sendto (s_sock , s_data_out , PACKET_SIZE , 0 ,
64+ (struct sockaddr * )& s_dest_addr , sizeof (s_dest_addr ));
65+
66+ if (sent < 0 ) {
67+ ESP_LOGW (TAG , "Failed to send UDP packet: errno %d, retry %d" ,
68+ errno , retry_count + 1 );
69+ retry_count ++ ;
70+
71+ // Small delay before retry (500 microseconds)
72+ esp_rom_delay_us (500 );
73+ } else if (sent != PACKET_SIZE ) {
74+ ESP_LOGW (TAG , "Incomplete UDP packet sent: %d of %d bytes" ,
75+ sent , PACKET_SIZE );
76+ }
77+ }
5278
5379 // Move remaining data to the beginning of the buffer
5480 s_data_in_head -= CHUNK_SIZE ;
@@ -104,6 +130,32 @@ esp_err_t scream_sender_init(void)
104130 return ESP_FAIL ;
105131 }
106132
133+ // Configure socket options for better reliability
134+ int opt_val ;
135+
136+ // Increase send buffer size
137+ opt_val = UDP_TX_BUFFER_SIZE ;
138+ if (setsockopt (s_sock , SOL_SOCKET , SO_SNDBUF , & opt_val , sizeof (opt_val )) < 0 ) {
139+ ESP_LOGW (TAG , "Failed to set SO_SNDBUF: errno %d" , errno );
140+ }
141+
142+ // Set timeout to prevent blocking too long on send
143+ struct timeval timeout ;
144+ timeout .tv_sec = 0 ;
145+ timeout .tv_usec = UDP_SEND_TIMEOUT_MS * 1000 ;
146+ if (setsockopt (s_sock , SOL_SOCKET , SO_SNDTIMEO , & timeout , sizeof (timeout )) < 0 ) {
147+ ESP_LOGW (TAG , "Failed to set SO_SNDTIMEO: errno %d" , errno );
148+ }
149+
150+ // Set QoS priority for audio traffic
151+ #if defined(IP_TOS ) && defined(IPTOS_DSCP_EF )
152+ // Use Expedited Forwarding (EF) for real-time audio
153+ opt_val = IPTOS_DSCP_EF ;
154+ if (setsockopt (s_sock , IPPROTO_IP , IP_TOS , & opt_val , sizeof (opt_val )) < 0 ) {
155+ ESP_LOGW (TAG , "Failed to set IP_TOS: errno %d" , errno );
156+ }
157+ #endif
158+
107159 // Initialize the destination address from settings
108160 app_config_t * config = config_manager_get_config ();
109161 memset (& s_dest_addr , 0 , sizeof (s_dest_addr ));
@@ -213,4 +265,4 @@ esp_err_t scream_sender_update_destination(void)
213265
214266 return ESP_OK ;
215267}
216- #endif
268+ #endif
0 commit comments