H.264 与 x264
H.264 (MPEG-4 AVC)
是一种高效的视频编码格式, 具有优越的压缩率, 能以较低的比特率提供较好的视频质量。就目前已成熟的视频编码格式而言, H.264的压缩率是最佳的。x264
是一个开源的 H.264 编码器, 以出色的编码效率而闻名, 是目前最佳的开放源码 H.264 编码工具。
H.264 Profiles
Wikipedia - Advanced Video Coding - Profiles
H.264 包含多个不同的 Profile, 用于适应不同的应用需求:
Baseline Profile
适合低成本和早期的移动设备使用, 目前已经很少采用
主要用于低成本应用, 对播放设备的性能要求不高, 此 profile 常见用于早期性能较低的行动设备 (如 Apple iPod)。现今行动设备性能比起以前强大许多, 此 profile 已经没有什么必要性了
Main Profile
早期用于电视广播, 现今应用不多
此 profile 原本是用于 SD 分辨率数码电视广播, 虽然没有实行, 然而被用于 HD 分辨率的电视广播。在 2004 年 High Profile 被开发之后, 此 profile 已经没有什么必要性了
早期的高性能行动播放设备(如 Sony PSP), 也是使用此 profile
High Profile
广泛用于 HD 应用, 如 Blu-ray、高清电视和游戏机
目前使用最广泛的 profile, 由其是 HD 分辨率电视应用 (如 Blu-ray / AVCHD 光盘储存、游戏机等电视多媒体播放器、HDTV DVB 广播服务)
现今的行动播放设备都可以流畅播放用此 profile 的 SD 分辨率影片, 中阶等级可以上 720p 分辨率, 高阶甚至可上 FullHD (软解可能会有点吃力, 硬解完全没问题)
High 10 Profile
支持更高位深和更精确的色彩取样, 主要用于专业领域
超越目前主流的消费型产品能力, 此 profile 建立在 High Profile 之上, 多了支持 10 bit 的精度, 色彩更精准。
以影片压制而言, 将 High Profile (8 bit) 影片重新编码输出为 H.264 High 10 Profile , 虽然色彩精度不会变, 但至少压缩率比输出 High Profile (8 bit) 还要高。
High 4:2:2 Profile
针对专业领域应用, 此 profile 建立在 High 10 Profile 之上, 多了支持 4:2:2 色彩取样, 比特深度达 10 bit
High 4:4:4 Predictive Profile
支持最高的色彩精度和无损压缩, 适合专业需求
此 profile 建立在 High 4:2:2 Profile 之上, 多了支持 4:4:4 色彩取样, 比特深度达 14 bit, 并且支持高效率无损重新编码, 且每张画面编码为三个独立的色彩平面
H.264 Frame Types
影片是由许多连续的 Frames 所组成, 但并不是所有 Frames 都是完整的画面, 那些 Frames 需要参考其他 Frames 才能解码出一张完整的画面。
H.264 使用三种不同类型的帧, 以减少数据量和提高压缩效率:
I-frame
独立完整的帧, 可直接解码, 不依赖其他帧
不需要参考其他 Frames, 是一张完整的画面。
IDR frame 为真正的 关键帧 (keyframes), P-frame & B-frame 不会越过 IDR frame 去参考其他 Frames, 所以可以随意跳转到任意 IDR frame 开始播放/解码, 而不会发生问题。
P-frame
记录相对于前一帧的差异, 只保存变化部分, 提高压缩效率
只记录了与之前的 Frames 相异的区块, 最多可以参考 16 张
之前的 Frames
播放 / 解码时需要参用到之前的 Frames 的部分资料, 才能解码出完整画面
在 x264 中, 你不能控制 P-frame 数量, 但你可以控制一个 P-frame 所能参考的 Frame 数量, 也就是 Reference frame (ref) 的数值
B-frame
利用前后两帧的信息记录差异部分, 具有最高的压缩率, 但增加了解码的复杂度
只记录了与前一张与后一张的 Frames 相异的区块, 压缩率高(由其是在低动态/低变化的影片), 播放/解码时需要用到前后两张的 Frames 的部分资料, 才能解码出完整画面
例子
(登入后即可检视图片)
从此图你可以发见 B-Frame 有用到前一张与后一张 Frame 的资料
播放 Farme 的顺序是依照 Frame 的时间点, 但解码顺序则不一定, 当 B-Frame 有用到后一张 Frame 的资料时, 就必须预先解码后一张 Frame
以上图为例
解码(处理)顺序: 1-2-4-3
显示(播放)顺序: 1-2-3-4
由于 P-/B-frame 不是完整的画面, 解码时必须参考其他 Frames, 所以你不能随意跳转到 P-/B-frame 上播放/解码
也就是说你如果播放 MPEG 视频格式, 当你跳播放时间点时, 正常而言, 并不会跳到你所选的时间点上, 而是最近的 IDR / I-frame
就压缩率而言…
由于 P-/B-frame 并不是完整的画面, 所以占用的空间较少, 提高这类 Frame 使用量可以有效提升压缩率, 但对画质几乎不会降低, 这代表可以使用较少的 bitrate (比特率) 达到维持一定画质
由以上得知, 在 bitrate 充足的情况下, 则不需要使用较多 B-frame、Reference frame (ref) , 多少 bitrate 为充足依影片内容为定, 高动态影片需要较多 bitrate, 低动则较少
至于使用时机…
提高 B-frame/ref 使用量可以降低 bitrate 的需求, 使用较少 bitrate 达到目标品质。低动态的影片可以使用较多的 B-frame, 高动态或是纯静态则是 P-frame 效果较好
对于相容性与硬件负担…
提高 B-frame/ref 使用量的副作用是降相容性以及提高硬件负担, 请先保证相容性再来追求压缩率。
而 ref 的副作用要比 B-frame 强, 例如 ref=16 这代表解码一个 P-frame 必须要连跳回 1~16 张之前的 Frames 取用资料。
x264 参数设置
Max B-frame (bframes)
控制 B-frame 的最大数量, 用于提升压缩率。
当设置 B-frame 时, 重复部分比较多/变化较少的 Frames 会被编码为 B-frame
Reference frame (ref)
指定 P-frame 的参考帧 (Frames) 数量。适度提高该值可优化压缩效果, 但会增加硬件解码负担
推荐设置
- Maximun B-frame: 3 - 6
- Reference frame (ref): 3 - 5
GOP 长度
指定关键帧 (IDR frame) 的间隔, 以便在跳转播放时保持解码的流畅性。
一个 keyframe (IDR frame) 到下一个 keyframe 的范围。
所以将 GOP 设为无限大虽然可以大幅增加压缩率, 但这样就不能随意跳转到其他时间点播放/解码。
建议维持 default 即可
Profile 和 Level
决定视频的压缩比和硬件性能需求, Profile 越高代表更高的压缩率和更复杂的编码, 但要求设备具有更高的解码性能
interlaced (隔行扫描)
支持编码输出 interlaced (隔行扫描) 的视频
x264 预设 (Preset)
x264 提供了多种预设选项 (Preset), 从 ultrafast 到 placebo, 用于控制编码速度和压缩效率的平衡。一般建议选择一个合适的预设以在编码效率和文件大小之间取得平衡。
速度越慢则会得到更好的压缩编码效率 (画质-比特率比 或 画质-视频大小比)。也就是说, 若你设置一个目标比特率或是视频大小, 则越慢的 Preset 将会得到更好的输出品质。而对于设置一个恒定品质 (CRF) 或是恒定量化值 (QP), 你可以透过选择更慢的 Preset 来简单的节省比特率 (也就是得到更小的视频大小)。
一般而言是使用你所能忍受的最慢 Preset。目前 Presets 依速度递减排序是
ultrafast
superfast
veryfast
faster
fast
medium
slow
slower
veryslow
placebo
该默认 Preset 是 medium, 忽略 placebo 因为它会比 veryslow 浪费更多时间而且效果差异太小。
而越慢的 Preset 其 Reference frame (ref) 值也越高, 例如 veryslow preset 的 ref 为 16。由于通常不需这么高的 ref, 你可以透过指定一个 Level 来限制 ref, 或是手动指定一个合理的 ref 值 (1 ~ 6)
x264 微调 (Tune)
Tune 参数则是针对特定内容类型 (如电影、动画、低延迟等) 优化的设置, 以改善特定应用的压缩效果。
压缩效果 | 内容类型 |
---|---|
film (电影) |
胶片电影、真人类型 |
animation (动画) |
例如卡通/日本动画 |
grain (胶片颗粒) |
颗粒感很重的影片。需要保留大量的 grain 时用 |
stillimage (静止影像) |
例如幻灯片效果的影片。静态图像编码时使用 |
PSNR | 优化 PSNR 值。 Wiki 为提高 psnr 做了优化的参数 |
SSIM | 优化 SSIM 值。 Wiki 为提高 ssim 做了优化的参数 |
Fast Decode (快速解码) | 用于低性能播放设备。可以快速解码的参数 (※ 压缩率极低) |
zerolatency (零延迟) |
处里时间低延迟。主要用于直播等。用在需要非常低的延迟的情况下, 比如电视电话会议的编码。 (※ 压缩率极低) |
参考实例
以下示例演示了如何应用基本选项来输出压缩高效的 H.264 视频文件
常规压缩 (适用于一般影片)
x264 --preset slow --crf 20 -o output.mp4 input.mp4
此命令使用 slow
预设, 以获得较高压缩比, CRF
设置为 20, 这将保持高画质
动画影片 (适用于卡通或动画类型)
x264 --preset medium --tune animation --crf 18 -o output.mp4 input.mp4
--tune animation
调整了编码参数, 以确保细节和动态画面效果适合动画
低延迟设置 (适用于直播或会议场景)
x264 --preset fast --tune zerolatency -o output.mp4 input.mp4
--tune zerolatency
适用于需要快速解码的实时场景
H.264 Level
H.264 的 Level 和 MaxDpbMbs 直接表示了播放设备的解码性能要求。Level 值越高, 设备的解码性能要求越高, 输出影片的压缩率也越高。
MaxDpbMbs 对应的 Level
Wikipedia - Decoded picture buffering
Level | MaxDpbMbs |
---|---|
1 | 396 |
1b | 396 |
1.1 | 900 |
1.2 | 2,376 |
1.3 | 2,376 |
2 | 2,376 |
2.1 | 4,752 |
2.2 | 8,100 |
3 | 8,100 |
3.1 | 18,000 |
3.2 | 20,480 |
4 | 32,768 |
4.1 | 32,768 |
4.2 | 34,816 |
5 | 110,400 |
5.1 | 184,320 |
5.2 | 184,320 |
6 | 696,320 |
6.1 | 696,320 |
6.2 | 696,320 |
关系方程式
强制指定 Level (限制 MaxDpbMbs)
ref = Min(Floor(MaxDpbMbs / (PicWidthInMbs * FrameHeightInMbs)), 16)
Floor(x)
: 向下取整数, 小数点直接舍去。 ex. Floor(1.9) = 1Min(x, y)
: 取比较小的数值。 ex. Min(2, 5) = 2
强制指定 ref
MaxDpbMbs = PicWidthInMbs * FrameHeightInMbs * ref
计算 PicWidthInMbs 和 FrameHeightInMbs (小数点向上取整)
PicWidthInMbs = Width / 16
FrameHeightInMbs = Height / 16
示例
输出设置
- 分辨率: 1280x1720
- Level: 不指定(自动)
- 参考帧 (ref): 4
计算 MaxDpbMbs:
$$ \text{MaxDpbMbs} = 80 \times 45 \times 4 = 14400 $$对照表得出 Level = 3.1
输出设置
- 分辨率: 1280x1720
- Level: 3.1
- 参考帧 (ref): 不指定(自动)
计算 ref
$$ \text{ref} = \min\left(\text{Floor}\left(\frac{18000}{80 \times 45}\right), 16\right) = \min(5, 16) = 5 $$输出 H.264 的 ref 可能为 4 或 5
同时强制指定 ref 与 Level
ref 设置值不能大于 5 (强制指定 ref 不能超过 Level 的限制)
x264 比特率控制
x264 提供多种输出品质和比特率控制方式, 主要包括 Constant Rate Factor (CRF) 和 2-Pass Bitrate。速率控制是指决定多少比特将被用于每帧的方法。这将决定视频大小且品质如何分布。而 CRF 的比特率分配效果是最佳的, 若无控制输出大小的需求则使用 CRF 即可。
Constant Quantizer (QP)
- 每个帧获得相同品质
设置 x264 以恒定量化值 (Constant Quantizer) 模式来编码视频。此方法可以让每帧获得相同品质 (设置值)。
设置值范围: 0 – 69
, 0 为最无损, 默认值为 23。比较低的数值会得到比较高的品质, 合理的范围 21 - 28。
Constant Ratefactor (CRF)
- 自动分配比特率以达到设置品质
此方法允许编码器自动分配比特速率来试着达到一定输出品质。让每帧得到它需要的比特率来保持所需的品质等级。CRF 会得到最佳的比特速率分配结果, 缺点是你不能直接指定一个目标比特率或是视频大小。
设置值范围为 0 – 51.0
, 0 为最高品质, 默认值为 23。比较低的数值会得到比较高的品质, 合理的范围 18 - 28。考虑 18 为视觉无损 (或接近), 所以它看起来应该与输入相同 (或接近) 但它技术上不是无损。
Bitrate
- 自定义比特率直接控制输出大小
- 可能导致比特率分配不均
自订 Bitrate 控制输出 Size, 直接编码输出视频。由于没有先扫描过一次, x264 无法得知影片各时间点的复杂程度。所以 x264 只能在编码中不断猜后之后的复杂程度, 这样将不能精准依各时间点的复杂程度等比例分配比特率, 因为如果之前分配了过多流量, 那么之后就必下修流量来使输出比特率平均值等于用户设置值
Bitrate, 2-Pass
- 先扫描视频以获取复杂程度, 之后精确分配比特率
- 耗时较长, 结果接近 CRF
此方法让编码器 1st-Pass 将会得知影片各个帧的复杂程度, 2nd-Pass 时依照输入视频各个帧的复杂程度等比例分配比特数输出, 并且最终平均比特速率会等于设置值。2-Pass 比特速率分配结果会接近 CRF, 缺点是耗费大量时间
1st-Pass CRF + 2-Pass Bitrate
- 结合以上两种方法, 效果接近 CRF, 耗时较长
此方法让编码器在 1st-Pass 时将会得知影片各个帧所需要的比特数, 2nd-Pass 时依照各个帧所需要的比特数等比例分配使最终比特速率总平均值会等于设置值。2-Pass 比特速率分配结果会接近 CRF, 缺点是耗费大量时间
x264 设置优先级
设置优先级顺序
preset -> tune -> 使用者设置选项 -> fast first pass -> profile -> level
当参数冲突时, 后者会取代前者或是影响前者
preset slower 的参数为
--b-adapt 2 --direct auto --me umh --partitions all --rc-lookahead 60 \
--ref 8 \
--subme 9 --trellis 2
当我设置
- x264 Preset: Slower
- Reference frame (ref): 4
等同于
--b-adapt 2 --direct auto --me umh --partitions all --rc-lookahead 60 \
--ref 4 \
--subme 9 --trellis 2
输出 H.264 的 Reference frame (ref) 为 4
当我设置
- x264 Preset: Slower
- Level: 3.2
输出 H.264 的 Reference frame (ref) 为 5
基本用法
基本语法
x264 [选项] -o <输出> <输入>
输入格式支持
- raw 输入
- YUV4MPEG (*.y4m)
- Avisynth (*.avs, 需要有支持的编码版)
- lavf / ffms 支持的输入格式
输出文件格式
.264
: Raw bytestream.mkv
: Matroska.flv
: Flash Video.mp4
: MP4 (需要有 GPAC 的编译版)
Piping 使用方法
64bit 的 x264
如果用了 64 位的 Windows, 就可以用 64 位的 x264。64 位的 x264 大约能比 32 位的 x264 快上 10% 左右, 能节省的时间还是比较可观的。但是用 AviSynth 输入时, 64 位的 x264 只接受 64 位的 AviSynth 输入, 32 位的 x264 只接受 32 位的 AviSynth。
虽然现在有 64 位的 AviSynth 和不少常用的滤镜, 但是大多数人还是愿意用 32 位的 AviSynth。那么如何用让 64位的 x264 配合 32 位的 AviSynth 呢?
方法是用 pipe。用命令行工具 (如 ffmpeg、mencoder 或 avs2yuv) 打开 avs, 让输出的 raw yuv 画面直接输入给 x264, 期间不产生中间文件。这个操作也是在命令行里实现的。
使用 ffmpeg 输入
先下载 ffmpeg 的 Windows 编译版, 可以用 static link 版本。和 x264 一样, ffmpeg 放在任何目录里都能运行, 假设和 x264、要进行编码的 input.avs 放在一个目录里
ffmpeg -i input.avs -f yuv4mpegpipe -an -v 0 - | x264 [options] --demuxer y4m -o output.264 -
先用 ffmpeg
打开 input.avs
, 并不指定输出的文件, 而是以 -
代替输出的文件。后面写 |
, 再写 x264
, x264 的选项和输出文件写法不变, 但是输入文件写 -
使用 mencoder 输入 (未测试)
mencoder 有很多有价值的滤镜, 用起来也很方便。libx264 可以编译进 mencoder 本身, 和单独的 x264 效果一样。mencoder 也可以打开 avs 文件, pipe 给 64 位的 x264。mplayer-ww 的命令行版里就带有 mencoder
同样假设 mencoder、x264 和要编码的 input.avs (1280x720) 在一个目录里
mencoder input.avs -vf format=yv12 -of rawvideo -ovc raw -nosound -o - | x264 [options] --input-res 1280x720 --input-csp yv12 -o output.264 -
使用 avs2yuv 输入
avs2yuv 本来是为了给 linux 上 wine 来用的, 因为 AviSynth 是运行在 Windows 的, 在 linux 里必须 wine avs2yuv 来打开 avs, 再 pipe 给 x264。当然也可以用来 pipe 给 64 位的 x264
同样假设 avs2yuv、x264 和要编码的 input.avs 在一个目录里
avs2yuv input.avs - | x264 [options] --demuxer y4m -o output.264 -
avs2yuv 的输出格式默认是 yuv4mpeg, x264 用 y4m 格式解码即可从中读取分辨率, 所以无须再用 --input-res
指定分辨率
以上介绍了 3 种方法, 个人比较倾向于用 ffmpeg。2pass 的编码也是像上面所讲的方法一样
原文
Wikipedia - H.264/MPEG-4 AVC
VideoLAN - x264
Wikipedia - x264
X264使用介绍 关于pipe
x264 - 高品质 H.264 编码器