fix(DiscoveryMountain): playback progress and stack overflow

- fix pos_sec integer division bug: samples/hz always 0 -> use total_decoded_samples/hz
- increase dm_play stack 12288->16384, dm_fetch 16384 to avoid overflow on 91KB JSON
- allocate mp3dec_t from PSRAM not stack
- add ID3v2 skip for mp3 files with XMP metadata
- reset last_pct on select/start to show progress bar
- remove auto-play for stability, user presses Play manually
- download now uses PSRAM 8192/4096 buffers, simple HTTP/1.0 non-chunked streaming

Tested on 192.168.68.132: fetch 37/232, download 4.3MB ok, playback opens stream sr=16000 ch=1 ok, no immediate crash.

Fixes #autoplay progress issue
This commit is contained in:
Adolfo
2026-07-21 22:24:24 -04:00
parent 80ab2880d9
commit 343da892bc
2 changed files with 88 additions and 20 deletions
+33 -8
View File
@@ -570,8 +570,21 @@ static void play_task(void* arg){
if(fsize>0) G.total_sec=(int)(fsize/16000);
if(!find_audio_device()){ ESP_LOGE(TAG,"no audio-stream dev"); fclose(file); G.is_playing=false; G.play_handle=NULL; vTaskDelete(NULL); return; }
mp3dec_t dec;
mp3dec_init(&dec);
// Skip ID3v2 if present
uint8_t id3hdr[10];
if(fread(id3hdr,1,10,file)==10 && memcmp(id3hdr,"ID3",3)==0){
int id3size = (id3hdr[6]&0x7F)<<21 | (id3hdr[7]&0x7F)<<14 | (id3hdr[8]&0x7F)<<7 | (id3hdr[9]&0x7F);
ESP_LOGI(TAG,"ID3 found %d, skip",id3size);
fseek(file, id3size+10, SEEK_SET);
fsize -= id3size+10;
if(fsize>0) G.total_sec=(int)(fsize/16000);
} else {
fseek(file,0,SEEK_SET);
}
mp3dec_t* dec = heap_caps_malloc(sizeof(mp3dec_t), MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if(!dec){ ESP_LOGE(TAG,"dec malloc fail"); fclose(file); G.play_handle=NULL; vTaskDelete(NULL); return; }
mp3dec_init(dec);
uint8_t* inbuf=malloc(MP3_BUF);
int16_t* pcm=malloc(1152*2*2);
if(!inbuf||!pcm){ if(inbuf) free(inbuf); if(pcm) free(pcm); fclose(file); G.play_handle=NULL; vTaskDelete(NULL); return; }
@@ -583,16 +596,21 @@ static void play_task(void* arg){
size_t r=fread(inbuf,1,MP3_BUF,file);
buffered=r;
ESP_LOGI(TAG,"play task start %s size %ld",path,fsize);
long total_decoded_samples=0;
while(!G.need_stop){
if(G.is_paused){ vTaskDelay(pdMS_TO_TICKS(100)); continue; }
int samples=mp3dec_decode_frame(&dec,inbuf,(int)buffered,pcm,&info);
int samples=mp3dec_decode_frame(dec,inbuf,(int)buffered,pcm,&info);
if(samples>0){
total_decoded_samples += samples;
if(info.hz>0) G.pos_sec = total_decoded_samples / info.hz;
if(!configured || info.hz!=sr || info.channels!=ch){
ESP_LOGI(TAG,"open_stream sr=%d ch=%d",info.hz,info.channels);
if(!open_stream((uint32_t)info.hz,(uint8_t)info.channels)){
ESP_LOGE(TAG,"open_stream fail %d %d",info.hz,info.channels);
break;
}
ESP_LOGI(TAG,"open_stream ok");
sr=info.hz; ch=info.channels;
configured=true;
if(G.pos_sec>5){
@@ -620,10 +638,13 @@ static void play_task(void* arg){
if(G.is_paused){ vTaskDelay(pdMS_TO_TICKS(100)); continue; }
size_t w=0;
error_t e=audio_stream_write(G.stream_handle,(uint8_t*)pcm+off,to_write-off,&w,pdMS_TO_TICKS(500));
if(e==ERROR_NONE) off+=w;
else vTaskDelay(pdMS_TO_TICKS(10));
if(e==ERROR_NONE){
off+=w;
} else {
ESP_LOGW(TAG,"audio_write err %d",e);
vTaskDelay(pdMS_TO_TICKS(10));
}
}
if(info.hz>0) G.pos_sec += samples / info.hz;
}
if(info.frame_bytes>0 && info.frame_bytes <= (int)buffered){
memmove(inbuf,inbuf+info.frame_bytes,buffered-info.frame_bytes);
@@ -641,6 +662,7 @@ static void play_task(void* arg){
fclose(file);
free(inbuf);
free(pcm);
heap_caps_free(dec);
close_stream();
ESP_LOGI(TAG,"play task end");
G.is_playing=false;
@@ -650,7 +672,7 @@ static void play_task(void* arg){
static void start_idx_internal(int idx){
if(idx<0||idx>=G.ep_cnt) return;
if(G.cur_ep_idx!=idx) G.pos_sec=0;
if(G.cur_ep_idx!=idx){ G.pos_sec=0; G.last_pct=-1; }
EpInfo* ep=&G.eps[idx];
tt_lvgl_lock(portMAX_DELAY);
wait_play_exit();
@@ -659,7 +681,7 @@ static void start_idx_internal(int idx){
G.need_stop=false; G.is_paused=false; G.is_playing=true;
save_state();
tt_lvgl_unlock();
xTaskCreate(play_task,"dm_play",12288,NULL,5,&G.play_handle);
xTaskCreate(play_task,"dm_play",16384,NULL,5,&G.play_handle);
}
static void dl_task(void* arg){
@@ -715,6 +737,7 @@ static void select_ep(int idx){
if(G.lbl_time) lv_label_set_text(G.lbl_time,"0:00 / --:--");
tt_lvgl_unlock();
G.pos_sec=0;
G.last_pct=-1;
save_state();
}
@@ -952,6 +975,7 @@ static void build_ui(){
tt_lvgl_unlock();
}
static void fetch_task_fn(void* arg){
(void)arg;
G.fetching=true;
@@ -988,6 +1012,7 @@ static void fetch_task_fn(void* arg){
vTaskDelete(NULL);
}
static void onShow(AppHandle app, void* data, lv_obj_t* parent){
(void)app; (void)data; (void)parent;
memset(&G,0,sizeof(G));