Fluent HTTPS stream receive

sdml12
Posts: 3
Joined: Mon Apr 14, 2025 12:54 pm

Fluent HTTPS stream receive

Postby sdml12 » Mon Apr 14, 2025 1:48 pm

I kinda listen radio via esp32s3.))
I receive stream like so(simplified for just speed measure):

Code: Select all

static void http_read_task(void* vParam)
{    
    //................
    timestamp1 = pdTICKS_TO_MS(xTaskGetTickCount());
    received = 0;
    while (1) {
        len = esp_http_client_read(client, http_buf, HTTP_BUF_SIZE);
        received += len;
        dt = pdTICKS_TO_MS(xTaskGetTickCount()) - timestamp1;
        if (dt) speed = received*1000/dt;
        ESP_LOGI(TAG, "Speed: %ld", speed);
    }
}
When stream is over plain HTTP - all fine, but when stream is over HTTPS there are options.
Some HTTPS stations are stuttering, in code above resulting speed is lower than bitrate.
In my understanding, this stations transmit stream at speed equal to audio bitrate and to have smooth sound we must constantly receive stream without gaps. As I think esp_http_client make gaps in receiving when TLS involved. It's not a network issue, on phone and same AP - all OK.
So, can somthing be done, without deep dive into low level programming of esp32?

Sprite
Espressif staff
Espressif staff
Posts: 10596
Joined: Thu Nov 26, 2015 4:08 am

Re: Fluent HTTPS stream receive

Postby Sprite » Tue Apr 15, 2025 12:09 am

If the bandwidth itself is sufficient, you may need to have a large-ish buffer between your http client and your MP3 player thing. E.g. run them in different tasks and have a large byte ringbuffer between the two.

sdml12
Posts: 3
Joined: Mon Apr 14, 2025 12:54 pm

Re: Fluent HTTPS stream receive

Postby sdml12 » Tue Apr 15, 2025 4:07 am

Of course I tried large buffer, and not. On mobile phone, with the same envirinment, playing starts instantly and have no issues. On esp - tens of seconds preliminary buffering doesn't help. Only one task like above, running just for speed measurement, produces solid speeed about 25℅ lower than bitrare for most "bad" station.

Sprite
Espressif staff
Espressif staff
Posts: 10596
Joined: Thu Nov 26, 2015 4:08 am

Re: Fluent HTTPS stream receive

Postby Sprite » Tue Apr 15, 2025 5:06 am

How large is your http_buf? Might be that increasing that improves things.

sdml12
Posts: 3
Joined: Mon Apr 14, 2025 12:54 pm

Re: Fluent HTTPS stream receive

Postby sdml12 » Tue Apr 15, 2025 9:53 am

Minimal working code for testing:

Code: Select all

#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_http_client.h"

#define TAG "SPEEDTEST"
#define HTTP_BUF_SIZE 16384

static void http_read_task(void* vParam)
{
    uint32_t received = 0, timestamp1, dt;
    char* http_buf  = malloc(HTTP_BUF_SIZE);
    esp_http_client_config_t config = {
        .url = "https://vrx.piro.moe/stream-256",       // 256 kbit/s, "nastiest" station I know) 
        //.buffer_size = HTTP_BUF_SIZE,
    };
    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_http_client_open(client, 0);
    esp_http_client_fetch_headers(client);
    
    timestamp1 = pdTICKS_TO_MS(xTaskGetTickCount());
    while (1) {
        received += esp_http_client_read(client, http_buf, HTTP_BUF_SIZE);
        dt = pdTICKS_TO_MS(xTaskGetTickCount()) - timestamp1;
        if (dt) ESP_LOGI(TAG, "Speed: %ld", (received/1024)*8000/dt);        // kbit/sec
    }
    //esp_http_client_cleanup(client);
}

static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) esp_wifi_connect();
    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&(((ip_event_got_ip_t*)event_data)->ip_info.ip)));
        xTaskCreate(&http_read_task, "http_read_task", 6000, NULL, 5, NULL);
    }
}

void app_main()
{
    nvs_flash_init();
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);
    esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_START, &event_handler, NULL, NULL);
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL);
    wifi_config_t wifi_config = { .sta = {
        .ssid = "MY_SSID",
        .password = "MY_PASSWORD",
        .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        .sae_pwe_h2e = WPA3_SAE_PWE_HUNT_AND_PECK,
        .sae_h2e_identifier = ""
    }};
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_start();
}
Last edited by sdml12 on Tue Apr 15, 2025 11:47 am, edited 1 time in total.

Sprite
Espressif staff
Espressif staff
Posts: 10596
Joined: Thu Nov 26, 2015 4:08 am

Re: Fluent HTTPS stream receive

Postby Sprite » Wed Apr 16, 2025 9:46 am

Interesting, thanks for posting the example code. I did some research, but it's not obvious where the bottleneck is. It's not the CPU power, both CPUs are like 95% idle. It's also not the hardware crypto accelerators; disabling them doesn't change the picture. Increasing the WiFi rx/tx buffers also does nothing. Think I need to pass this on to others, maybe they know.

chegewara
Posts: 2505
Joined: Wed Jun 14, 2017 9:00 pm

Re: Fluent HTTPS stream receive

Postby chegewara » Wed Apr 16, 2025 7:58 pm

Hi, just an observation:
I dont think its esp32 issue. When i changed API to use perform instead of read then i see this with buffer size 8kB (i am testing on P4)

Code: Select all

I (12740) SPEEDTEST: HTTP_EVENT_ON_DATA, len=2800
I (13071) SPEEDTEST: HTTP_EVENT_ON_DATA, len=2800
I (13073) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (14095) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (15118) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (16144) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (16145) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (17167) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (18191) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (19233) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (19234) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (20246) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (21265) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (22290) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (23310) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (25358) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (25358) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4082
I (25359) SPEEDTEST: HTTP_EVENT_ON_DATA, len=14
I (25360) SPEEDTEST: HTTP_EVENT_ON_DATA, len=2960
I (25365) SPEEDTEST: HTTP_EVENT_ON_DATA, len=1099
I (26382) SPEEDTEST: HTTP_EVENT_ON_DATA, len=2997
I (26384) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (27406) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
I (28431) SPEEDTEST: HTTP_EVENT_ON_DATA, len=4096
Another thing is that http read stuck for about 1000ms (sometimes more) every 4096 bytes read, no matter what buffer size is (its good to test with size 64).

sdml12
Posts: 3
Joined: Mon Apr 14, 2025 12:54 pm

Re: Fluent HTTPS stream receive

Postby sdml12 » Thu Apr 17, 2025 3:17 pm

I have news.))
Setting CONFIG_LWIP_TCP_WND_DEFAULT = 8192 (no more, no less) solves this.

nilesh_kale
Espressif staff
Espressif staff
Posts: 5
Joined: Wed May 22, 2024 6:17 am

Re: Fluent HTTPS stream receive

Postby nilesh_kale » Fri Apr 18, 2025 7:03 am

You can refer to the configuration settings used in the IDF/examples/wifi/iperf example, both from the default and target-specific sdkconfig, to optimize for maximum throughput.

I tried simulating a similar scenario on an ESP32-C3 using those configurations and observed a noticeable improvement in speed. I suggest you try it as well, and it would be helpful if you could share your observations.

Additionally, you might consider enabling the keep-alive options in the esp_http_client_config to further improve performance.

Who is online

Users browsing this forum: Google [Bot], Qwantbot and 8 guests