11个版本
0.2.2 | 2023年6月4日 |
---|---|
0.2.1 | 2023年6月4日 |
0.1.7 | 2023年6月1日 |
0.1.6 | 2023年5月31日 |
#195 in 视频
每月40次下载
在pfv-cli中使用
105KB
2K SLoC
快速视频
作为漂亮的视频的后续版本,设计为最小的视频编解码器
目标是提高
- 质量
- API设计
- 编解码器结构
- (希望)性能
当前编解码器版本为2.1.0
为什么?
PFV的目标是成为视频领域的QOA(即,一个极简编解码器,旨在优先考虑简单性和解码速度,而不仅仅是压缩比,并且完全免费使用,适用于游戏等离线应用程序的回放)。
性能的主要目标是Theora。虽然这个Rust库未能击败Theora的解码性能,但我已经编写了一个配套的纯C库,它确实击败了Theora的解码性能(特别是在扩展到使用系统中的所有可用核心时,因为它是一个极端的并行算法):libpfvdec
未来探索的目标将是通过计算着色器进行GPU解码 - 因为每个宏块已经可以完全并行处理,因此简单地将DCT系数上传到GPU并在GPU上完全进行解码应该很简单,直接解码到游戏就绪的纹理中。
用法
编码视频
创建pfv_rs::enc::Encoder,输入帧,然后写入结果
use pfv_rs::enc::Encoder;
let out_video = File::create("my_video.pfv").unwrap();
let mut enc = Encoder::new(out_video, width, height, framerate, quality, num_threads).unwrap();
// feed in frames as VideoFrames (1 keyframe every 15 frames)
for (idx, frame) in &my_frames.iter().enumerate() {
if idx % 15 == 0 {
enc.encode_iframe(frame).unwrap();
} else {
enc.encode_pframe(frame).unwrap();
}
}
// finish PFV stream (will also be automatically called if encoder is dropped)
enc.finish().unwrap();
解码视频
创建pfv_rs::dec::Decoder,并在每一帧上调用advance_delta,传递自上一帧以来的经过时间,并使用闭包处理帧
use pgv_rs::dec::Decoder;
let mut dec = Decoder::new(my_file, num_threads).unwrap();
while dec.advance_delta(delta_time, &mut |frame| {
// do something with returned &VideoFrame
}).unwrap() {}
或者,您也可以调用advance_frame来直接跳到下一帧,而不传递delta参数。签名相同。
这两个函数还会在文件中还有更多数据要读取时返回Ok(true),或者在解码器达到文件末尾时返回Ok(false)。
算法概述
视频帧编码就视频编解码器而言相当标准。帧被分割成16x16宏块,这些宏块进一步分为8x8子块。每个子块都通过DCT变换和量化来减少存储所需的位数。系数进一步使用熵编码进行压缩。
PFV还采用4:2:0色度子采样 - 因此U和V色度平面在每个轴上都是Y平面的尺寸的一半。
存在三种帧:丢弃帧、I-帧和P-帧。
- 丢弃帧不进行编码,只是被视为自上一帧以来没有变化。
- I-帧只编码完整帧。
- P-帧将帧编码为相对于上一帧的差分。每个宏块都有一个像素偏移,用于从上一帧复制,宏块还可以编码每像素的差分(量化到0..255的范围)。
音频
自编解码器版本2.0.0起,已从规范中删除音频。
您可以使用任何音频流格式与PFV视频流一起使用,无论它是嵌入到某种容器格式中还是直接与视频文件一起发送。对于轻量级的CPU要求,QOA是音频轨道的一个不错的选择。
依赖关系
~230–530KB