fix(ncm): META 改「变化+低频心跳」,不再每 100ms 刷 launcher(M10)

根因: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 日志。
This commit is contained in:
AskaEth committed 2026-11-05 13:00:28 +08:00
1 parent 35a636ef42
commit 7f4e18b0ed
3 files changed
+175 -13

No files matched your search

+35 -13
View File
@@ -1,12 +1,14 @@
/* play/ipc_media.c — 媒体会话 IPC 最小客户端(SDK 尚无媒体封装,App 内用 meow_ipc.h 帧格式直连)。
*
* 连接:AF_UNIX SOCK_STREAM 到 MEOW_IPC_SOCK(缺省 /usr/data/meow_ipc.sock)。HELLO(app_id,
* MF_PLAYBACK) 注册为媒体源;之后**同一连接**周期发 MSG_META(~1s,进度随播放推进)并阻塞等
* launcher 下发 MSG_PLAYCTL(播放/暂停/上下曲/seek/toggle)。launcher 经该连接 fd 回发(meow_media.c
* send_playctl 用最近活跃会话的 fd)。无 socket/launcher 不跑 → 优雅跳过(打日志不崩)。
* MF_PLAYBACK) 注册为媒体源;之后**同一连接**上报 MSG_META 并阻塞等 launcher 下发 MSG_PLAYCTL
* (播放/暂停/上下曲/seek/toggle)。launcher 经该连接 fd 回发(meow_media.c send_playctl 用最近
* 活跃会话的 fd)。META 节奏见 meta_gate.h(变化 + 低频心跳,不再是 1s 定时;M10 修洪泛)。
* 无 socket/launcher 不跑 → 优雅跳过(打日志不崩)。
* 线程模型:独立线程(main 起了 meow_ui_run 阻塞;播放线程归 player_manager,本线程只做 IPC 收发)。
*/
#include "../ncm_app_internal.h"
#include "meta_gate.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -23,6 +25,12 @@ static int g_thr_on;
static int g_quit;
static volatile int g_req_focus_player = 0; /* 任务3:launcher 请求「回到播放页」(UI 线程消费) */
/* M10:META 上报闸(变化 + 低频心跳;时间用 core 单调钟)。
* 旧实现 `if (now - last_meta >= 1000)` 依赖 meow_ui_time_ms(),真机该值高 32 位是垃圾
* (REPORT §42)→ 条件恒真 → 每个 IPC 轮次都发 META(真机 launcher 日志 ~100ms 一帧、
* 单次启动 21016 帧),launcher 每帧写日志+归并会话,SD 写放大到整机卡死。 */
static ncm_meta_gate g_meta_gate;
static const char *sock_path(void)
{
const char *e = getenv("MEOW_IPC_SOCK");
@@ -92,8 +100,10 @@ static int read_frame(int fd, uint16_t *type, uint8_t *rbuf, uint32_t rcap)
return (int)len;
}
/* 组并发送一条 META。 */
static void send_meta(int fd, uint32_t req_id)
/* 组并发送一条 META。返回 1=已发 / 0=闸判定不必发 / -1=写失败。
* 是否发由 meta_gate 决定:状态/元数据变化立即发;播放中位置偏移 ≥5s 重锚;心跳 5s/30s;
* 硬下限 250ms(任何路径都不快于 4 帧/秒)。now_ms 必须是单调毫秒(ncm_monotonic_ms)。 */
static int send_meta(int fd, uint32_t req_id, int64_t now_ms)
{
m_meta_t mm;
memset(&mm, 0, sizeof mm);
@@ -135,7 +145,21 @@ static void send_meta(int fd, uint32_t req_id)
mm.flags |= MF_ART | MF_COVER;
}
if (lyric_count() > 0) mm.flags |= MF_LYRIC;
send_frame(fd, MSG_META, req_id, &mm, sizeof mm);
ncm_meta_snap s;
s.state = (int)mm.state;
s.pos_ms = (int)mm.pos_ms;
s.dur_ms = (int)mm.dur_ms;
s.flags = (int)mm.flags;
s.title = mm.title;
s.artist = mm.artist;
s.album = mm.album;
s.artwork = mm.artwork;
if (!ncm_meta_gate_should_send(&g_meta_gate, &s, now_ms)) return 0;
if (send_frame(fd, MSG_META, req_id, &mm, sizeof mm) != 0) return -1;
meow_log(MEOW_LOG_DEBUG, "ipc: meta sent state=%u pos=%u/%u", mm.state, mm.pos_ms, mm.dur_ms);
return 1;
}
static void apply_playctl(const m_playctl_t *c)
@@ -177,9 +201,8 @@ static void *ipc_thread(void *arg)
uint16_t htype;
if (read_frame(fd, &htype, hb, sizeof hb) < 0) { close(fd); return NULL; }
send_meta(fd, 2); /* 首条注册媒体源(state=0 未播也登记,start 播后自动成源) */
send_meta(fd, 2, ncm_monotonic_ms()); /* 首条注册媒体源(state=0 未播也登记,start 播后自动成源) */
uint64_t last_meta = 0;
while (!g_quit && !g_app_quit) {
struct pollfd p;
p.fd = fd; p.events = POLLIN;
@@ -197,11 +220,9 @@ static void *ipc_thread(void *arg)
} else if (pr < 0 && errno != EINTR) {
break;
}
uint64_t now = meow_ui_time_ms();
if (now - last_meta >= 1000) {
send_meta(fd, (uint32_t)(now & 0x7FFFFFFF));
last_meta = now;
}
/* M10:不再定时无脑发;send_meta 内部按 meta_gate 判「变化 / 位置偏移 / 低频心跳」。 */
int64_t now_ms = ncm_monotonic_ms();
send_meta(fd, (uint32_t)(now_ms & 0x7FFFFFFF), now_ms);
}
close(fd);
return NULL;
@@ -284,6 +305,7 @@ int ipc_media_start(void)
{
if (g_thr_on) return 0;
g_quit = 0;
ncm_meta_gate_init(&g_meta_gate); /* M10:首帧必发(注册媒体源),之后按变化/心跳 */
if (ncm_thread_create(&g_thr, ipc_thread, NULL) != 0) return -1;
pthread_detach(g_thr);
g_thr_on = 1;