根因:ipc_media 主循环 `if (now - last_meta >= 1000)` 同样依赖 meow_ui_time_ms()
的坏 64 位值(REPORT §42)→ 条件恒真 → 每个 IPC 轮次都发 MSG_META。
launcher 日志 meow_20261105_122541.log:单次启动 21016 条
`ipc: META app=dev.player.ncm state=0 pos=0/0 -> ACK`,间隔 ~100ms,且全是
无变化的静止帧;launcher 每帧写 2 行日志+归并会话,SD 写放大到整机卡死。
修复:
- 新增 app/play/meta_gate.{h,c}(纯逻辑):状态/时长/标题/歌手/专辑/封面/歌词
标志变化 → 立即报;播放中位置偏移 ≥5s 重锚(launcher 自己按 last_active 外推);
心跳播放中 5s / 非播放 30s;硬下限 250ms(任何路径 ≤4 帧/秒);时钟回退不下溢;
字符串按发送侧截断长度比较(超长标题不得恒判「变了」)。
- ipc_media.send_meta 改为「组快照 → 闸判定 → 才发」,删除 1s 定时器;
时间改 ncm_monotonic_ms();首帧仍必发(注册媒体源);发送走 DEBUG 日志。
67 lines
3.0 KiB
C
67 lines
3.0 KiB
C
/* play/meta_gate.h — 媒体会话 META 上报闸(M10:META 洪泛修复点;纯逻辑,宿主可驱动)。
|
||
*
|
||
* 背景(真机证据):launcher meow_20261105_122541.log 里 21016 条 `ipc: META app=dev.player.ncm
|
||
* state=0 pos=0/0 rc=0 -> ACK`,间隔 ~100ms(每次 launcher 收帧都要写日志+归并会话)。
|
||
* 旧 ipc_media 的节奏是 `if (now - last_meta >= 1000)`,同样依赖 meow_ui_time_ms() 的 64 位差值;
|
||
* 真机该值高 32 位是垃圾(REPORT §42)→ 条件几乎恒真 → 每个 IPC 轮次都发 META,
|
||
* 1s 心跳退化成 10Hz 洪泛,把 launcher 的 SD 写/会话归并拖满,整机卡死。
|
||
*
|
||
* 修复后的上报策略(不再是定时器,而是「变化 + 低频心跳」):
|
||
* - 状态/时长/标题/歌手/专辑/封面/歌词标志变化 → 立即上报(用户操作要即时可见);
|
||
* - 播放中位置相对上次上报偏移 ≥ 5s(含 seek 前后跳)→ 上报,给 launcher 重锚进度
|
||
* (launcher meow_media_display_pos 会按 last_active 自行外推,5s 足够);
|
||
* - 心跳:播放中 5s、非播放 30s(保活会话/防 launcher 会话超时清理);
|
||
* - 硬下限 250ms:任何路径(含状态抖动)都不快于 4 帧/秒。
|
||
* 时间基准由调用方给单调钟(ipc_media 传 core 的 ncm_monotonic_ms())。
|
||
*/
|
||
#ifndef NCM_META_GATE_H
|
||
#define NCM_META_GATE_H
|
||
|
||
#include <stdint.h>
|
||
|
||
/* 与 meow_ipc.h 的 m_meta_t.state 同口径(MF_PLAYBACK 会话状态)。 */
|
||
enum {
|
||
NCM_META_ST_STOPPED = 0,
|
||
NCM_META_ST_PLAYING = 1,
|
||
NCM_META_ST_PAUSED = 2,
|
||
NCM_META_ST_BUFFER = 3,
|
||
};
|
||
|
||
/* 一次上报快照(字符串由调用方持有,本模块只拷贝比较,不接管所有权)。 */
|
||
typedef struct {
|
||
int state; /* NCM_META_ST_* */
|
||
int pos_ms;
|
||
int dur_ms;
|
||
int flags; /* MF_ART/MF_COVER/MF_LYRIC 位 */
|
||
const char *title;
|
||
const char *artist;
|
||
const char *album;
|
||
const char *artwork;
|
||
} ncm_meta_snap;
|
||
|
||
typedef struct {
|
||
int inited;
|
||
int state;
|
||
int dur_ms;
|
||
int flags;
|
||
int last_pos_ms; /* 上次上报时的播放位置(判进度偏移/seek) */
|
||
int64_t last_send_ms; /* 上次上报的单调毫秒 */
|
||
char title[128];
|
||
char artist[128];
|
||
char album[128];
|
||
char artwork[192];
|
||
} ncm_meta_gate;
|
||
|
||
#define NCM_META_POS_RESEND_MS 5000 /* 播放中位置偏移(ms)触发重报 */
|
||
#define NCM_META_HB_PLAY_MS 5000 /* 播放中心跳 */
|
||
#define NCM_META_HB_IDLE_MS 30000 /* 非播放心跳 */
|
||
#define NCM_META_MIN_GAP_MS 250 /* 硬下限:任何情况下 ≤ 4 帧/秒 */
|
||
|
||
void ncm_meta_gate_init(ncm_meta_gate *g);
|
||
|
||
/* 返回 1=现在应当发送(内部已把本次快照记为「已上报」);0=不必发。
|
||
* now_ms=单调毫秒(建议 ncm_monotonic_ms())。未初始化时首调必发(注册媒体源)。 */
|
||
int ncm_meta_gate_should_send(ncm_meta_gate *g, const ncm_meta_snap *s, int64_t now_ms);
|
||
|
||
#endif /* NCM_META_GATE_H */
|