Files
MeowOS-For-R3P2/patch_v2/ncm_app/app/play/stream_src.h
T
AskaEth 3d70a3dd2c feat: M6.10–M6.19 批量收编 + M6.19 推卡验收
- M7 launcher 重写 5 期(虚拟化宫格/meow_theme 单一权威/横幅动画/自定义 PIN 键盘)
- OOM 通用化(cachegov 上收 SDK)、自动切歌根治、meowpanel jv_free 泄漏修复、Hello 滚动卡顿修复
- ncm 歌词 UI / 媒体通知封面 / 封面分辨率 640
- 5 bug 修复:ncm 后台化 UI 叠层+点击穿透、再进 ncm 桌面叠层、播放页新旧 UI 叠层抢刷脏区(meow_ui_gfx 恢复边沿整帧重画)、PIN 亮屏亮度跳(keys.c meow_panel_on 按 settings_brightness_clamped 恢复)、通知中心封面显歌单封面(cover.c save_cover_raw 加 is_song + 命中块守卫)
- 四 App 统一重链新 meow_ui.a 51caee4a;M6.19=0.8.19 固件 2d2331f2 推卡自刷验收全绿
2026-09-03 12:16:01 +08:00

92 lines
5.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* play/stream_src.h — 边下边播共享流源(REPORT §21,方案 NCM_STREAM_PLAY A:写穿缓存)。
*
* 模型:下载线程把字节顺序写进 .tmp(ncm_cache 写者 write(2) 直写,不走 stdio 缓冲),
* 解码线程经本对象 pread 同一文件——落盘的文件本身就是下载缓冲,内存里无第二份拷贝。
* 写端每写完一块调用 stream_src_note_written() 推进可读边界并 broadcast 唤醒读端;
* 下载结束(完成/中断)stream_src_finish() 置 final;切歌/停止 stream_src_abort()。
*
* 读回调契约(实测红线 F7):stream_src_read_cb 严格 fread 语义——填满才返回,
* 真 EOF(final/failed/abort 且数据耗尽)才短读;否则 minimp3 把短读当 EOF 假播完。
* dr_flac 回调语义不同(返回实际读到的字节数):本对象同样先尽力填满再返回,
* 两种契约同时满足。
*
* 本层只依赖 pthread/pread/write,不依赖 core(保持 app/play 层自含)。
*/
#ifndef NCM_STREAM_SRC_H
#define NCM_STREAM_SRC_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stream_src stream_src_t;
/* seek 原点(与 drflac_seek_origin 同值,避免本头依赖 dr_flac.h)。 */
enum { STREAM_SRC_SEEK_SET = 0, STREAM_SRC_SEEK_CUR = 1, STREAM_SRC_SEEK_END = 2 };
/* 下载路径:tmp_path 已由 ncm_cache_open 创建(写端持有自己的写 fd);
* 本函数只开只读 fd(pread 与写端 write 无偏移冲突),written 从 0 起由写端推进。 */
int stream_src_open_stream(stream_src_t **out, const char *tmp_path);
/* 断点续传(阶段3,§5.2):path 已含既存前缀(.part),written 置为前缀字节数——
* 读端 read_pos=0 可立即读到已下前缀(秒开播),写端从 written 继续推进。 */
int stream_src_open_stream_at(stream_src_t **out, const char *path, uint64_t written);
/* 缓存命中路径:完整文件,written=final=size,read 永不阻塞(同一套读回调)。 */
int stream_src_open_static(stream_src_t **out, const char *path, uint64_t size);
void stream_src_close(stream_src_t *s);
/* ---- 写端(下载线程) ---- */
/* 数据已落盘(ncm_cache_write 成功)后调用:推进可读边界 + 唤醒读端。 */
void stream_src_note_written(stream_src_t *s, uint64_t n);
/* 下载结束:err==0=完成(final=written),否则中断(final=written + failed=err)。
* 之后 read_cb 数据耗尽即短读(真 EOF),解码自然结束于截断点(F5)。 */
void stream_src_finish(stream_src_t *s, int err);
/* 切歌/停止:唤醒所有等待,read 立即按 EOF 短读返回;下载回调应随后返回 NZ 中止 http。 */
void stream_src_abort(stream_src_t *s);
int stream_src_aborted(stream_src_t *s); /* 下载回调每块开头廉价检查 */
/* ---- 预缓冲 ---- */
/* 等 written >= need;final/failed/abort 提前返回。timeout_ms 为单次等待上限
* (调用方在循环里套切歌护栏)。返回 1=满足,0=超时,<0=已结束/失败/中止。 */
int stream_src_wait(stream_src_t *s, uint64_t need, int timeout_ms);
/* 同步 peek(pread,不动 read_pos):magic 探测用。off+n 超出 written 的部分不读,
* 返回实际读到字节数。 */
size_t stream_src_peek(stream_src_t *s, void *buf, size_t n, uint64_t off);
/* ---- minimp3 回调(MP3D_READ_CB / MP3D_SEEK_CB) ---- */
size_t stream_src_read_cb(void *buf, size_t size, void *ud);
int stream_src_seek_cb(uint64_t pos, void *ud);
/* ---- dr_flac 回调(drflac_read_proc / drflac_seek_proc / drflac_tell_proc) ---- */
size_t stream_src_drflac_read(void *ud, void *buf, size_t bytes_to_read);
int stream_src_drflac_seek(void *ud, int offset, int origin); /* origin=STREAM_SRC_SEEK_* */
int stream_src_drflac_tell(void *ud, int64_t *cursor);
/* ---- 统计 / 停滞联动 ---- */
/* underrun=read_cb 追上下载(无数据可给)的等待次数;wait_ms=累计等待 ms。 */
void stream_src_stats(stream_src_t *s, int *underruns, uint64_t *wait_ms);
/* 单次 read 等待 >1s 置位(播放线程下一轮对 audiod pause(1),恢复后 pause(0))。
* 取走即清零。 */
int stream_src_take_stalled(stream_src_t *s);
/* ---- page-cache 治理(OOM_PAGECACHE_GOVERNANCE §2.3:underrun/refault 检测)----
* refault = pread 处「数据已在盘上(written>read_pos)但读出耗时 >50ms」——DONTNEED 丢页后
* 重读 TF 的信号,区别于网络 underrun(avail==0 等待)。SDK meow_cachegov 据此做 A 回退。
* 播放线程读 refaults 落 g_play 取证;回调由 SDK(meow_cachegov_note_refault)提供,
* 未链 SDK 时弱符号为空(host sim 兼容)。 */
int stream_src_refaults(stream_src_t *s);
/* 当前解码逻辑读指针(stream_src_seek_cb 改写)。 */
uint64_t stream_src_read_pos(stream_src_t *s);
uint64_t stream_src_written(stream_src_t *s);
uint64_t stream_src_final(stream_src_t *s); /* 0=下载中;>0=最终大小(完成=全长,中断=截断点) */
int stream_src_failed(stream_src_t *s); /* 0=无错误;<0=下载/IO 错误码 */
#ifdef __cplusplus
}
#endif
#endif /* NCM_STREAM_SRC_H */