尧图精选

零拷贝的魔法:video-compress-cj 如何用 Surface 直通硬件编解码,大幅降低延迟

🕒 发布时间:2026/11/2 23:14:27 📁 来源:尧图网络
零拷贝的魔法video-compress-cj 如何用 Surface 直通硬件编解码大幅降低延迟【免费下载链接】video-compress-cj一个高性能的视频压缩器使用硬件解码和编码API(MediaCodec)。项目地址: https://gitcode.com/Cangjie-TPC/video-compress-cjvideo-compress-cj是一款面向仓颉语言的高性能视频压缩开源库支持 H.264/H.265 硬件解码与 AAC 音频压缩提供高、中、低三档质量输出。它的核心卖点是把硬件解码 → 硬件编码两个环节用Surface 直通串联起来——视频帧从解码器出来全程不经过 CPU 内存直接穿进编码器。这就是零拷贝Zero-Copy视频压缩的典型实现。 一句话概括传统压缩要把每一帧视频帧搬到内存再搬回硬件而 video-compress-cj 让帧在硬件之间直达延迟更低、功耗更省、速度更快。为什么传统视频压缩慢CPU 拷贝的隐形开销大多数视频压缩工具的数据流是这样的阶段传统方案数据去向1. 解封装从 mp4 中读取视频数据→ CPU 内存2. 硬件解码解码器把帧写回系统内存→CPU 内存第 1 次拷贝3. 送入编码器从内存把帧再推给硬件编码器→CPU 内存第 2 次拷贝4. 封装编码后的码流写入新 mp4→ 磁盘注意第 2、3 步以 1080P 30fps 计算每一帧裸帧约 3MB每秒要来回搬运上百 MB 数据。这不仅占用宝贵的 CPU 缓存和内存带宽还会让压缩速度明显拖慢——帧的搬运本身成了瓶颈而不是解码编码。Surface 直通零拷贝视频压缩的三条关键路径video-compress-cj 的 C 引擎位于 videocompress_ffi/src/main/cpp/ 目录零拷贝由三个紧密配合的步骤完成。第一步拿到硬件编码器的输入 Surface项目启动编码器后调用OH_VideoEncoder_GetSurface获取编码器的输入 Surface一块 GPU 可写入的显存画布保存到全局共享的MutexManager中// videocompress_ffi/src/main/cpp/video/encoder/VideoEnc.cpp int32_t VideoEnc::GetSurface() { return OH_VideoEncoder_GetSurface(venc_, mutexManager-nativeWindow); }见 VideoEnc.cpp#L179-L182。同时编码器被配置为AV_PIXEL_FORMAT_SURFACE_FORMAT像素格式VideoEnc.cpp#L73意味着它只接受 Surface 输入从接口层面就杜绝了走内存的路径。第二步把硬件解码器的出口对准同一块 Surface解码器配置时同样使用AV_PIXEL_FORMAT_SURFACE_FORMAT格式VideoDec.cpp#L94启动时通过OH_VideoDecoder_SetSurface把输出目标设置为编码器刚拿到的那块 Surface// videocompress_ffi/src/main/cpp/video/decoder/VideoDec.cpp int32_t VideoDec::SetOutputSurface() { return OH_VideoDecoder_SetSurface(vdec_, mutexManager-nativeWindow); }见 VideoDec.cpp#L109-L112。两块硬件设备共享同一个nativeWindow定义于 tools.h#L38-L51在总控流程 cjcodec.cpp#L56-L88 中先创建编码器取 Surface再创建解码器绑定 Surface顺序保证了先有画布再往上画。第三步RenderOutputData —— 帧永远不出硬件解码完成后项目没有调用取帧接口而是调用OH_VideoDecoder_RenderOutputDataVideoDec.cpp#L278传统路径 解码器 → 系统内存 → 你的代码 → 编码器 两次内存搬运 直通路径 解码器 ═══ Surface 显存 ═══ 编码器 零内存搬运对开发者来说解码线程VideoDec::OutputFunc只需要确认渲染完成真正的数据搬运全部由图形驱动在硬件内部完成。帧数据自始至终留在 GPU 显存中CPU 只负责指挥不参与搬运。兜底机制RK 芯片上的自动降级Surface 直通依赖图形驱动的 BufferQueue 支持。项目做了硬件识别当检测到编解码器能力名称中包含rk瑞芯微芯片平台驱动对 Surface 格式支持有限时解码和编码都会自动降级为AV_PIXEL_FORMAT_RGBA内存格式VideoDec.cpp#L92-L98、VideoEnc.cpp#L71-L77。硬件环境像素格式数据路径主流平台Surface 直通SURFACE_FORMAT解码器 → Surface → 编码器 ✅ 零拷贝RK 芯片平台自动降级RGBA解码器 → 内存 → 编码器兼容性优先这种能直通就直通不能直通就兼容的策略保证了库在不同真机上的可用性。完整数据流从文件 fd 到压缩后的 MP4零拷贝不止于 Surface。整条链路都在就地处理仓颉层打开输入/输出文件把**文件描述符fd**直接传给原生层见 video_compressor.cj#L62-L69避免了整文件读进内存解封装器DeMuxer按轨道 fd 直读提取视频/音频流视频走 Surface 直通硬件转码音频解码后经 AAC 重新编码封装器Muxer把编码输出直接写回输出 fd生成压缩后的 mp4。总入口 cjcodec.cpp 中的NativeCompressStart函数就是这条流水线的总装车间建封装器 → 建编码器取 Surface → 建解码器绑 Surface → 启动全部流水线最后等待 EOS 收尾。如何快速上手 video-compress-cj库的对外 API 极简核心只有一个类VideoCompressor和一个方法compressVideo三档质量一键切换接口详情见 doc/feature_api.md。在仓颉工程中引入本地依赖后调用只需几行let compressor VideoCompressor() let result compressor.compressVideo(context, inputFilePath, CompressQuality.COMPRESS_QUALITY_HIGH)压缩完成后结果对象会返回新视频在沙盒中的路径与状态码。如需完整体验可将仓库克隆到本地作为三方源码依赖git clone --recursive https://gitcode.com/Cangjie-TPC/video-compress-cj.git然后在 DevEco Studio 中编译videocompressor模块即可。总结Surface 直通解码器输出与编码器输入共享同一块显存画布视频帧零拷贝直达是低延迟高吞吐的关键自动降级识别 RK 等平台自动切换内存格式兼顾性能与兼容全链路 fd 直传从解封装到封装不落地整文件内存占用稳定⚡开发者友好仓颉侧一行compressVideo调用三档质量开箱即用。对于需要批量转码、相册压缩、上传前瘦身等场景这种硬件直通架构让大文件压缩从等待变成顺手——这正是零拷贝的魔法所在。【免费下载链接】video-compress-cj一个高性能的视频压缩器使用硬件解码和编码API(MediaCodec)。项目地址: https://gitcode.com/Cangjie-TPC/video-compress-cj创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →