fix(ncm §32): 内存瘦身修 OOM 被杀 —— 封面降采样(8.28MB→0.78MB) + 瞬态 rbuf 缩减 + 线程栈显式

真机 dmesg 实锤:OOM Kill ncm (score 460, anon-rss 26.9MB, 设备 56MB)。
画像:封面全分辨率 RGBA 8.28MB(1448x1448 原生解码驻留) 是最大可控块。

瘦身(按收益排序):
1. sdk meow_ui_img 新增纯增量 meow_img_downscale + cover.c cover_cap(≤480px)
   → 封面 8.28MB→0.78MB,-7.65MB(mem_sim 实测 PASS)。
2. ncm_api.c 瞬态响应 rbuf:song_url→64KB、lyric/song_detail/cloudsearch/user_playlist→256KB
   (detail/track_all 保 1MB)。
3. ncm_app_internal.h 新增 ncm_thread_create(显式 128KB 栈),替换全部 14 处 pthread_create。
4. 滑动窗口/meta 复核零回退(window_sim:608B/首,6000 首 280KB 恒定)。

验证:mem_sim 封面收益 PASS + host home/player 渲染 OK + stream_sim/player_flow_sim/
window_sim/search_sim/cache_evict_sim 全 PASS + test_ncm_core host+mipsel(qemu) PASS
+ build_ncm.sh -Wall -Wextra 0 warning。真机 scp 播放在跑确认(缓存曲,0 播放请求)。

新 ncm md5 44fa16fe(text 1015150/bss 1362500)。正式部署留主会话。
This commit is contained in:
AskaEth committed 2026-09-02 03:43:42 +08:00
1 parent 202caaf66b
commit 68ce46a5d8
19 files changed
+368 -19

No files matched your search

+1 -1
View File
@@ -722,7 +722,7 @@ void autoplay_maybe(void)
meow_log(MEOW_LOG_INFO, "autoplay: triggered, sel='%s'", buf);
char *sel = strdup(buf);
pthread_t t;
if (pthread_create(&t, NULL, autoplay_worker, sel) == 0) pthread_detach(t);
if (ncm_thread_create(&t, autoplay_worker, sel) == 0) pthread_detach(t);
else free(sel);
}
+16 -1
View File
@@ -117,6 +117,19 @@ static void save_cover_raw(const char *path, size_t len)
#define COVER_RETRY_MAX 8 /* 连续失败放弃次数(UI 重进页/切歌会重新提交目标) */
/* 内存瘦身:封面解码后按显示上限降采样驻留。网易云全尺寸封面(如 1448×1448)解码成
* RGBA = 8MB,而应用显示只需 ≤480px(播放页黑胶方图+歌词页模糊铺底均 ≤ 屏幕 480 宽)——
* 缩到 480×480 = 0.9MB,省 ~7MB anon(设备 RAM 仅 56MB,OOM 真机被杀,最高优先级)。
* 若已 ≤上限(小缩略图)则原样保留。返回本函数处理后的图(可能替换/释放旧图)。 */
#define NCM_COVER_DECODE_MAX 480
static meow_img *cover_cap(meow_img *im)
{
if (!im) return NULL;
meow_img *small = meow_img_downscale(im, NCM_COVER_DECODE_MAX);
if (small) { meow_img_free(im); return small; } /* 已缩放:释放原始大图,换小图驻留 */
return im; /* 本就够小:保留原图 */
}
static void *cover_worker(void *arg)
{
(void)arg;
@@ -168,6 +181,8 @@ static void *cover_worker(void *arg)
}
}
}
/* 内存瘦身:全尺寸封面解码后降采样到 ≤480px 驻留(省 ~7MB anon,OOM 修复)。 */
if (img) img = cover_cap(img);
if (!img) {
/* 失败:指数退避重试,连续 COVER_RETRY_MAX 次放弃(不无声死等;
* 目标保留期间 UI 每帧重请求由 cover_request 去重挡住)。 */
@@ -218,7 +233,7 @@ void cover_request(const char *url)
pthread_mutex_unlock(&g_cm);
if (!g_thr_on) {
g_thr_on = 1;
if (pthread_create(&g_thr, NULL, cover_worker, NULL) == 0)
if (ncm_thread_create(&g_thr, cover_worker, NULL) == 0)
pthread_detach(g_thr);
else
g_thr_on = 0;