今天接到一个需求,需要把YUV序列转换为无损的MP4。一开始准备是用x264编码,把QP设置为0。但这样压缩后,我比较了一下,发现实际上还是有损的。而且QP设置为0后,普通的播放器根本不能打开,只能用基于ffmpeg的播放器才能正常播放。后来想到265有Transform Quantizer Bypass(TQB)技术,本身就就支持无损编码,遂进行了尝试。
ffmpeg把YUV无损转换为MP4的命令行代码:
ffmpeg -s 1920x1080 -pix_fmt yuv420p -r 60 -i .\BallUnderWater_1920x1080_60fps.yuv
-c:v libx265 -preset ultrafast -x265-params lossless=1 output_265.mp4
主要在x265指定了lossless=1(开始无损压缩)参数。
现在我们虽然得到了转换后的MP4文件,但是我想进一步验证得到的文件到底是不是无损的。在查询官方文档的时候我看了官方给出了两种验证方式:
lossless compression ratio
就表明是无损压缩通过计算hash和framehash,发现原始视频的hash和frame与转换后得到的MP4文件的hash和framehash值完全一致。着说明确实是无损压缩。
更进一步,既然是无损压缩,那么把MP4文件转换为YUV(我们叫做新YUV),再计算原始YUV和新YUV的PSNR,那么每一帧的PSNR肯定都是无穷大。为啥是先把MP4文件转换为YUV呢?这是因为MP4文件的timebase和原始YUV的timebase不一致,那么两者的每一帧不能一一对应,其计算出的PSNR就不准确了。 话不多说,开动!
ffmpeg -i .\BallUnderWater_1920x1080_60fps.mp4 newyuv.yuv
ffmpeg -s 1920x1080 -pix_fmt yuv420p -r 60 -i .\BallUnderWater_1920x1080_60fps.yuv -s 1920x1080
-pix_fmt yuv420p -r 60 -i .\newyuv.yuv -lavfi psnr=stats_file=psnr_logfile.txt -f null -
最终的PSNR结果如下面两张图,可以看出PNSR确实为无穷大。
平均PNSR
每一帧的PSNR