只解决 TTMusic 当前的一个缺口:
SACD ISO 中 DST 压缩轨道无法提取不做下面这些事:
ijkplayer 播放链路audiodecoder.sacd 整个 Kodi 插件搬进项目第一版目标很单一:
LocalMusic 的 ISO 提取在遇到 DST 轨道时,也能输出 .dsfTTMusic 当前已经有完整的 ArkTS ISO 提取链路:
现有能力已经覆盖:
.dsftaskpool 进度回传当前卡住的唯一原因是这里主动拦截了 DST:
并且在扇区处理逻辑里,DST 帧目前直接返回失败:
推荐的最小方案不是把 audiodecoder.sacd 整套搬进来,而是只抽它的 libdstdec。
原因:
audiodecoder.sacd 里真正解决 DST 的核心是 lib/libdstdecsrc/sacd/*、SACDAudio.cpp、Settings.cpp、Kodi addon 外壳大多是播放器插件包装,不是你当前缺的能力也就是说,当前最小缺口不是 “不会读 SACD ISO”,而是 “已经拿到完整 DST frame 后,不会解成 DSD frame”。
audiodecoder.sacd这个仓库确实有用,但直接整仓接入成本不合适。
强耦合点包括:
Kodisrc/SACDAudio.cpp 是 Kodi 音频解码器实例src/sacd/sacd_media.* 依赖 kodi::vfs::CFilesrc/sacd/sacd_reader.h 依赖 kodi::addon::AudioDecoderInfoTaglib/libdsdpcm 是 DSD 转 PCM 播放用,不是抽轨必需对 TTMusic 当前任务来说,真正要用的是:
lib/libdstdec而不是:
Addon.cppSACDAudio.cppSettings.cpplib/libdsdpcmlib/id3v2lib推荐接到 entry 的 libentry.so,不要先塞进 ijkplayer_napi。
理由:
entry 里已经有现成的 native bridge 模式libentry.so 调原生方法@Concurrent + libentry.so 的实际用例:
所以推荐目录:
entry/src/main/cpp/third_party/sacd/libdstdec/entry/src/main/cpp/sacd_dst_decoder.hentry/src/main/cpp/sacd_dst_decoder.cppentry/src/main/cpp/napi_init.cppentry/src/main/cpp/CMakeLists.txtentry/src/main/cpp/types/libentry/Index.d.ts从 audiodecoder.sacd 拷贝:
lib/libdstdec/binding/dst_decoder_mt.cpplib/libdstdec/binding/dst_decoder_mt.hlib/libdstdec/binding/semaphore.hlib/libdstdec/decoder/decoder.cpplib/libdstdec/decoder/decoder.hlib/libdstdec/ac.hlib/libdstdec/common.hlib/libdstdec/consts.hlib/libdstdec/ct.hlib/libdstdec/fh.hlib/libdstdec/fr.hlib/libdstdec/segment.hlib/libdstdec/stream.hsrc/SACDAudio.cppsrc/SACDAudio.hsrc/Addon.cppsrc/Addon.hsrc/Settings.cppsrc/Settings.hsrc/sacd/sacd_core.*src/sacd/id3_tagger.*src/sacd/sacd_dsf.*src/sacd/sacd_dsdiff.*src/sacd/sacd_dsd.*lib/libdsdpcm/*lib/id3v2lib/*libdstdec 当前最主要的外部耦合是日志:
common.h 里包含了 <kodi/General.h>这一块建议改成 TTMusic 自己的日志适配:
hilog换句话说,第一版不需要 Kodi 文件系统,不需要 Kodi 设置,不需要 Kodi AudioDecoder 类型。
继续保留 ArkTS 现有能力:
.dsf 写出taskpool 进度更新新增一个 “DST frame -> DSD frame” 的 native 解码器会话。
推荐原生接口:
export interface NativeModule {
createSacdDstDecoder(channelCount: number, samplerate?: number, framerate?: number): number;
decodeSacdDstFrame(decoderId: number, dstFrame: ArrayBuffer): ArrayBuffer;
releaseSacdDstDecoder(decoderId: number): void;
}
默认参数建议:
samplerate = 2822400framerate = 75这里 75 不是拍脑袋,是 audiodecoder.sacd 的 sacd_disc_t::get_framerate() 直接返回的值。
不要做成每帧都重新初始化 decoder。
原因:
dst_decoder_t::init() 有初始化成本第一版直接用单线程 slot 即可:
dst_decoder_t(1)这样每次 decode() 都能同步拿到当前帧输出,不需要额外做 flush 逻辑。
IsoArchiveTaskHelper.ets第一版建议只改这个文件:
当前 extractSacdTrackEntry() 里这段需要调整:
frameFormat === DST 时,不再直接返回失败建议改成:
channelCount 创建一个 DST decoder sessionprocessSacdSector() 继续负责把 DST packet 组装成完整 frameDST frame 就绪,调用 native decodeSacdDstFrame()DSD frame 后,继续复用当前 writeSacdFrameToDsf()当前逻辑里这段是阻断点:
if (assembler.dstEncoded) {
return false;
}
第一版应改成:
assembler.dstEncoded === false:
writeSacdFrameToDsf()assembler.dstEncoded === true:
assembler.buffer.subarray(0, assembler.size) 送去 native 解码writeSacdFrameToDsf()因为扇区读取和写文件仍在 ArkTS,当前这些逻辑都不用重写:
advanceIsoExtractProgress()reportIsoExtractProgress()taskpool.Task.sendData()这也是这个方案比“整套搬 C++ 抽轨器”更适合当前仓库的原因。
sacd_dst_decoder.cpp建议内部结构:
struct SacdDstDecoderSession {
int64_t id;
uint32_t channelCount;
uint32_t samplerate;
uint32_t framerate;
size_t dsdFrameSize;
std::unique_ptr<dst_decoder_t> decoder;
std::vector<uint8_t> decodeBuffer;
};
createSacdDstDecoder职责:
channelCountdst_decoder_t(1)init(channelCount, 2822400, 75)decodeBufferdecodeSacdDstFrame输入:
decoderIdArrayBuffer dstFrame职责:
ArrayBufferdecoder->decode(dstBytes, dstSize, &outPtr, &outSize)decodeBuffer 打包成新的 ArrayBuffer 返回输出:
releaseSacdDstDecoder职责:
CMakeLists.txt在 entry/src/main/cpp/CMakeLists.txt 中:
entry 目标增加 sacd_dst_decoder.cpplibdstdec 源码一并编进 entrythird_party/sacd/libdstdec 相关头文件目录libace_napi.z.so 和 hilog_ndk.z第一版不需要:
WavPackIconvKodi在 entry/src/main/cpp/types/libentry/Index.d.ts 里追加:
createSacdDstDecoder(channelCount: number, samplerate?: number, framerate?: number): number;
decodeSacdDstFrame(decoderId: number, dstFrame: ArrayBuffer): ArrayBuffer;
releaseSacdDstDecoder(decoderId: number): void;
ArkTS 使用方式仍保持和 SMB bridge 一样:
import nativeBridge from 'libentry.so';
先把 libdstdec 编进 libentry.so,做一个本地自测接口:
DST frameDSD frame先确认:
ArrayBuffer 往返正常在 IsoArchiveTaskHelper.ets 里只改 DST 分支:
DST 保持原样DST 走 native 解码跑 3 组真机测试:
确保:
最后再考虑是否补:
这些都不应该挡住第一版上线。
如果实际验证发现 TTMusic 当前 ArkTS 的 DST frame 组装和 sacd_disc_t::read_frame() 在某些碟片上不兼容,再退回到第二方案:
src/sacd/scarletbook.*src/sacd/sacd_disc.*sacd_media.*但这应该是 Plan B,不是第一步。
理由很简单:
audiodecoder.sacd 顶层是 GPL-2.0 / GPL-2.0-or-later 路线,接入前必须先明确你项目能否接受对应分发约束。
libdstdec/binding/dst_decoder_mt.* 文件头本身写的是 LGPL-2.1 or later,但整仓来源仍然需要你按第三方合规去核。
这个问题不是技术问题,是分发问题。
libdstdec/common.h 当前带 kodi::Log,需要改成本地日志。
第一版目标只保证:
.dsf不保证:
这些可以后续再做。
对 TTMusic 来说,最小、最稳、最符合当前代码结构的方案是:
audiodecoder.sacd 整套libdstdecDST frame -> DSD frame 这一步补到 libentry.so如果你下一步要我继续做,实现顺序建议是:
libdstdec 接进 entry/src/main/cpplibentry.so 的 3 个 native API 做出来IsoArchiveTaskHelper.ets 的 DST 分支接上去