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

+11 -5
View File
@@ -9,6 +9,12 @@
#include <stdlib.h>
#include <string.h>
/* 响应缓冲上界(内存瘦身,OOM 修复):多数接口响应远小于 1MB,按需给尺寸避免每次调用
* 都 malloc 1MB 堆峰值(播放中 song_url/lyric/song_detail 并发,几 × 1MB 是可砍的瞬态)。
* 仅 playlist detail / track_all(全量 trackIds,最多 NCM_TRACKID_MAX 条)保留传统 1MB。 */
#define RESP_SMALL (64 * 1024) /* song_url:url+字段,实际 ~1KB */
#define RESP_MED (256 * 1024) /* lyric/song_detail/playlist/cloudsearch:实际 ≤100KB */
const char *ncm_api_level_str(int level) {
switch (level) {
case NCM_LEVEL_SURROUND: /* "sky" + immerseType=c51(song_url 内处理) */
@@ -168,7 +174,7 @@ int ncm_api_user_playlist(const char *device_id, const char *cookie, const char
api_json_t c; memset(&c, 0, sizeof c);
int rc = api_post(device_id, cookie, "/api/user/playlist", json, NCM_CRYPT_WEAPI,
NCM_RESP_MAX, &c);
RESP_MED, &c);
if (rc != NCM_OK) return rc;
int arr = ncm_json_path(&c.j, "playlist");
@@ -248,7 +254,7 @@ int ncm_api_song_detail(const char *device_id, const char *cookie, const int64_t
api_json_t c; memset(&c, 0, sizeof c);
int rc = api_post(device_id, cookie, "/api/v3/song/detail", json, NCM_CRYPT_EAPI,
2 * 1024 * 1024, &c);
RESP_MED, &c);
if (rc != NCM_OK) return rc;
int arr = ncm_json_path(&c.j, "songs");
@@ -271,7 +277,7 @@ int ncm_api_song_url(const char *device_id, const char *cookie, const char *id,
api_json_t c; memset(&c, 0, sizeof c);
int rc = api_post(device_id, cookie, "/api/song/enhance/player/url/v1", json, NCM_CRYPT_EAPI,
NCM_RESP_MAX, &c);
RESP_SMALL, &c);
if (rc != NCM_OK) return rc;
int d0 = ncm_json_path(&c.j, "data[0]");
@@ -497,7 +503,7 @@ int ncm_api_lyric(const char *device_id, const char *cookie, const char *id,
api_json_t c; memset(&c, 0, sizeof c);
int rc = api_post(device_id, cookie, "/api/song/lyric", json, NCM_CRYPT_EAPI,
NCM_RESP_MAX, &c);
RESP_MED, &c);
if (rc != NCM_OK) return rc;
if (lrc && lrc_sz) { lrc[0] = 0; ncm_json_path_str(&c.j, "lrc.lyric", lrc, lrc_sz); }
if (tlrc && tlrc_sz) { tlrc[0] = 0; ncm_json_path_str(&c.j, "tlyric.lyric", tlrc, tlrc_sz); }
@@ -521,7 +527,7 @@ static int cloudsearch_post(const char *device_id, const char *cookie, const cha
snprintf(json, sizeof json, "{\"s\":\"%s\",\"type\":%d,\"offset\":%d,\"limit\":%d,\"total\":true}",
esc, type, offset > 0 ? offset : 0, limit > 0 ? limit : 30);
return api_post(device_id, cookie, "/api/cloudsearch/pc", json, NCM_CRYPT_WEAPI,
NCM_RESP_MAX, c);
RESP_MED, c);
}
/* 解析一处「歌单对象数组」(cloudsearch type=1000)。id 可为数字/字符串(均文本拷贝)。 */