xmoezzz/amv_decoder

GitHub: xmoezzz/amv_decoder

一个实验性的 AMV 格式解析与解码项目,填补了 KiriKiri2/KiriKiriZ 相关视频格式的逆向工程工具空白。

Stars: 7 | Forks: 0

# amv_decoder `amv_decoder` 是一个实验性的 Rust 项目,用于解析(部分解码)**AJPM / “Alpha Movie”** 视频格式, 该格式被部分 **KiriKiri2** 和 **KiriKiriZ (krkrz)** 引擎使用的作品采用。 本仓库是逆向工程工作的产物。它与任何引擎或游戏厂商无关,未获其认可或支持。 ## 状态 - 容器解析器和数据包拆分器已足够稳定,可用于迭代式逆向工程(RE)工作。 ## 功能 - 读取 40 字节文件头(小端序,魔术数 `0x4D504A41` / `AJPM`)。 - 加载全局量化表。 - 从 `header_size` 开始迭代帧数据包。 - 转储原始数据包字节和每个分段的数据块以便分析。 - 将帧数据包解码为 RGBA 帧(实验性),并可输出 PPM 图像用于快速检查。 ## 快速开始 前置条件 - Rust 稳定工具链。 构建 ``` cargo build ``` 转储数据包(对新样本推荐的第一步) ``` cargo run -- dump testcase/1.amv --out out_dump ``` 这将生成: - `out_dump/index.json` - `out_dump/frames/frame_000000.packet.bin` - 对于数据包类型 A(参见格式说明),还包括: - `out_dump/frames/frame_000000.seg0.bin` - `out_dump/frames/frame_000000.seg1.bin` 解码帧(实验性) ``` cargo run -- decode testcase/1.amv --out out_decode --ppm true ``` 这会为每个帧生成输出: - `out_decode/frame_000000.rgba`(原始 RGBA 字节) - `out_decode/frame_000000.ppm`(仅 RGB 的 PPM,若指定 `--ppm true`) ## 测试 基于样本的解码测试被标记为 `#[ignore]`,因为 `testcase/1.amv` 未被提交。 本地运行被忽略的测试: ``` cargo test -- --ignored --nocapture ``` ## AMV 容器说明 所有整数均为小端序。 ### 文件头(40 字节) 基于观察到的加载器行为的最小可用布局: - `u32 magic` = `0x4D504A41` (`AJPM`) - `u32 unknown_04` - `u32 revision`(预期为 `0`) - `u32 header_size`(观察到 `168` 或 `232`) - `u32 unknown_10` - `u32 frame_count` - `u32 fps_num` - `u32 fps_den` - `u16 width` - `u16 height` - `u8 attr` - `u8[3] reserved` 紧接在 40 字节头部之后,文件包含全局量化表,其大小为 `header_size - 40`: - 类型 A 模式下为 `128` 字节 - 类型 B 模式下为 `192` 字节 引擎侧用于选择寻址路径的标志(IDA 输出中的 `stream+29`)由 `attr` 派生。 在实践中,这与是否存在 Alpha 数据相关。 ### 帧数据包类型 A(寻址路径 `sub_10016D20`) 该数据包类型以 24 字节头部开始,并被拆分为两个有效载荷分段。概念上: - `u32 tag` - `u32 chunk_size`(首个 8 字节之后的数据字节数) - `u32 frame_id` - `i16 p0` - `i16 p1` - `u16 w_aligned`(16 的倍数) - `u16 h_aligned`(16 的倍数) - `u32 seg0_len` - `u8 seg0[seg0_len]` - `u8 seg1[chunk_size - 16 - seg0_len]` 观察行为表明: - `seg0` 经过 zlib 压缩,解压后得到 `w_aligned * h_aligned` 字节的平面。 - `seg1` 是熵编码的 DCT 系数流。 - 每个宏块解码 6 × 8×8 块(与无 Alpha 的 YCbCr 4:2:0 一致)。 ### 帧数据包类型 B(寻址路径 `sub_10017570`) 该数据包类型以 20 字节头部开始,并包含单个有效载荷数据块: - `u32 tag` - `u32 chunk_size`(首个 8 字节之后的数据字节数) - `u32 frame_id` - `i16 p0` - `i16 p1` - `u16 w_aligned`(16 的倍数) - `u16 h_aligned`(16 的倍数) - `u8 payload[chunk_size - 12]` 观察行为表明: - 每个宏块解码 10 × 8×8 块。 - 块似乎被拆分到多个 Huffman/比特流上下文中。 - 10 个块的结构与 Y(4 块)+ Cb(1 块)+ Cr(1 块)+ Alpha(4 块)一致,但这仍是一个 工作假设,直到完全匹配组合代码。 ### 熵编码模型(高层概览) 两种数据包类型均使用类似 JPEG 的 8×8 块编码模型: - DC 系数使用预测器并通过 Huffman 编码分类,后跟额外比特。 - AC 系数使用 Huffman 编码的(RUN,SIZE)符号,采用 Zig-Zag 顺序以及 EOB/ZRL 语义。 - 系数经过全局量化表反量化并通过 IDCT 重建。 - 最终输出被合成到帧缓冲区中。 ## 许可证 MPL-2.0(详见 `Cargo.toml`)。
标签:Alpha Movie, AMV, FFmpeg, KiriKiri2, KiriKiriZ, krkrz, PPM, RGBA, Rust, SEO: AMV 解码, SEO: KiriKiri 视频解析, SEO: 逆向分析, 云资产清单, 可视化界面, 图像处理, 多媒体解析, 实验性解析器, 容器格式, 小端解析, 帧分割, 帧解码, 文件格式, 游戏视频, 网络流量审计, 视频解析, 视频解码, 逆向工程, 通知系统, 量化表