0. 前言
在H264 Extended Profile中就引入了B帧编码,一直以来同行都对B帧的意义存在争议:
正方:B帧能够大幅减少视频码率,并提高运动场景下的清晰度;
反方:B帧对码率和清晰度没多大帮助
笔者针对这个争议找了一个视频,用x264和Android MediaCodec测试验证B帧到底有没有优化效果。
1. 什么是B帧
1.1 什么是B帧?
B帧法(B frame)是双向预测的帧间压缩算法。当把一帧压缩成B帧时,它根据相邻的前一帧、本帧以及后一帧数据的不同点来压缩本帧,也即仅记录本帧与前后帧的差值。
1.2 B帧的优点
一般地,I帧压缩效率最低,P帧较高,B帧最高。
B帧能够提升运动场景清晰度。
PS:有些专家说对高速运动的场景收益是负向,但是本人没有验证过。
1.3 B帧的缺点
由于B帧参考了前后帧,带来更所以编码复杂度更高,也提高了解码复杂度。
2. B帧编码测试
2.1 软编码实验
2.1.1 测试方案
对同一个视频,通过ffmpeg/x264进行转码,在相同比特率等条件,选择开启/关闭B帧,对比PSNR。
2.1.2 测试视频
理论上B帧对运动场景编码,所以本次实验采用一个跳舞的视频,视频信息系如下:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘dance_test.mp4’:
Metadata:
major_brand : qt
minor_version : 0
compatible_brands: qt
creation_time : 2018-08-06 13:08:32
genre : aweme_6585043390285482760
Duration: 00:00:13.60, start: 0.000000, bitrate: 5375 kb/s
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, smpte170m/bt709/bt709), 540x960, 5244 kb/s, 30 fps, 30 tbr, 600 tbn, 1200 tbc (default)
Metadata:
creation_time : 2018-08-06 13:08:32
handler_name : Core Media Data Handler
encoder : H.264
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 124 kb/s (default)
Metadata:
creation_time : 2018-08-06 13:08:32
handler_name : Core Media Data Handler
2.1.3 FFmpeg/x264命令
1 --bframes <integer> (x264)
2 -bf <integer> (FFmpeg)
B-frames are a core element of H.264 and are more efficient in H.264 than any previous standard. Some specific targets, such as HD-DVD and Blu-Ray, have limitations on the number of consecutive B-frames. Most, however, do not; as a result, there is rarely any negative effect to setting this to the maximum (16) since x264 will, if B-adapt is used, automatically choose the best number of B-frames anyways. This parameter simply serves to limit the max number of B-frames. Note that Baseline Profile, such as that used by iPods, does not support B-frames. Recommended default: 16
ffmpeg转码非B帧视频示例:
ffmpeg -i dance_test.mp4 -c:v libx264 -profile:v high -level:v 4.0 -r 30 -s 540x960 -b:v 1500k -g 200 -bf 0 -c:a copy -movflags faststart -y b0_1500.mp4
ffmpeg转码B帧视频示例:
ffmpeg -i dance_test.mp4 -c:v libx264 -profile:v high -level:v 4.0 -r 30 -s 540x960 -b:v 1500k -g 200 -bf 1 -c:a copy -movflags faststart -y b1_1500.mp4
2.1.4 评估方法
采用PSNR评估B帧对视频质量的提升,命令如下:
ffmpeg -video_size 540x960 -i dance_test.yuv -video_size 540x960 -i b0_1500.yuv -lavfi psnr="stats_file=psnr.log" -f null -
2.1.5 测试结果
码率 B帧设置 PSNR
1500 是 PSNR y:30.96 u:43.46 v:42.37 average:32.55 min:31.15 max:38.65
1500 否 PSNR y:30.46 u:42.97 v:41.87 average:32.05 min:30.61 max:38.42
2000 是 PSNR y:32.76 u:44.56 v:43.49 average:34.33 min:32.64 max:40.77
2000 否 PSNR y:32.13 u:43.93 v:42.84 average:33.70 min:32.22 max:40.48
测试结论: B帧没有明显收益
2.2 Android硬编码实验
Android 平台设置 Profile参考我的另一篇笔记:Android MediaCodec H264编码设置Main Profile & High Profile
另外,Android平台只有高通芯片支持B帧编码,而且Android现有的API中没有开启B帧功能的接口,默认是关闭B帧的,只有小米和三星等少数平台开启了B帧编码。
2.2.1 测试方案
Android平台只有高通支持B帧,并且受限于Android系统,无法控制B帧是否开启,除非修改Android源代码。目前只有小米和三星两家的高通手机对高通支持比较好。
所以本人选取两台手机:
机型 Android CPU 是否支持B帧
Mi 5s 7.0 骁龙821 是
Pixel 9.0 骁龙821 否
输入同一个视频,用硬编码进行转码,参数设置如下:
Bitrate: 3000Kb/s
Bitrate-Mode: VBR
Profile: High Profile
Frame-Rate: 30
Frame-Interval: 1
2.2.2 测试视频
同软编码实验。
2.2.3 评估方法
同软编码实验。
2.2.4 测试结果
机型 是否支持B帧 PSNR
mi5s 是 PSNR y:44.02 u:42.74 v:44.60 average:43.83 min:42.15 max:46.13
pixel 否 PSNR y:44.10 u:42.91 v:44.77 average:43.94 min:42.08 max:46.13
2.2.5 总结
很尴尬……硬编码测试的结果都说明B帧收益不大-_-!!
3. 结论
B帧不管是软编码还是硬编码都没什么收益。