关于初学视频编码的同学来讲,除了了解关于视频编码的一些理论的知识以及代码之外,还有一项必备的技能就是能够在各种操作系统之下,熟练的去跑视频编解码的代码,以及怎么配置相关的配置文件,如何将编解码之后的数据统计出来都是要求必须熟练掌握的。今天详细讲一下关于在本地Windows下如何顺利地编解码视频序列,并在正确测试的基础上在远程计算资源上对所有序列进行统一的测试。(AI的本地少帧测试+远程全帧编码)RA的配置类似,关于帧结构的问题我有空再抽时间写一下。本教程适用于本人实验室的同学们参考使用,当然实验室之外的同学也可以参考本教程~
本地少帧测试是为了大致测试自己的方案的性能,如果本地测试良好则可以在远程计算机上完整的测试整套方案
(注意:我这里所使用的都是VTM6.0及其相关的配置文件)
关于VTM参考软件如何安装我在之前的博客都写过一个教程:
H.266/VVC代码学习笔记1:VTM5.0的下载和安装简单而实用的教程
一、在测试之前需要一些准备工作。配置cfg文件。cfg文件就是视频编码中一些基础的配置文件,如果在自己电脑上测试的话,只需要将VTM参考软件的文件目录下的cfg文件稍微配置一下就好,配置步骤如下:
1.找到VTM参考软件的文件目录下的cfg文件(总共有四个,AI、RA、LDP、LDB),根据自己的需要去修改对应的cfg,以下的例子我都拿AI(All Intra)举例子:
2.打开cfg文件:
将标蓝的地方用下面的指令替换:
#======== File I/O ===============
InputFile : .../C/BasketballDrill_832x480_50.yuv
InputBitDepth : 8 # Input bitdepth
InputChromaFormat : 420 # Ratio of luminance to chrominance samples
FrameRate : 50 # Frame Rate per second
FrameSkip : 0 # Number of frames to be skipped in input
SourceWidth : 832 # Input frame width
SourceHeight : 480 # Input frame height
FramesToBeEncoded : 40 # Number of frames to be coded
Level : 3.1
BitstreamFile : str37.bin
ReconFile : rec37.yuv
替换好后如下:
#======== File I/O ===============
InputFile : E:/RQH/TestSquence/C/BasketballDrill_832x480_50.yuv
InputBitDepth : 8 # Input bitdepth
InputChromaFormat : 420 # Ratio of luminance to chrominance samples
FrameRate : 50 # Frame Rate per second
FrameSkip : 0 # Number of frames to be skipped in input
SourceWidth : 832 # Input frame width
SourceHeight : 480 # Input frame height
FramesToBeEncoded : 40 # Number of frames to be coded
Level : 3.1
BitstreamFile : str37.bin
ReconFile : rec37.yuv
#======== Profile ================
Profile : next
#======== Unit definition ================
MaxCUWidth : 64 # Maximum coding unit width in pixel
MaxCUHeight : 64 # Maximum coding unit height in pixel
MaxPartitionDepth : 4 # Maximum coding unit depth
#======== Coding Structure =============
IntraPeriod : 1 # Period of I-Frame ( -1 = only first)
DecodingRefreshType : 1 # Random Accesss 0:none, 1:CRA, 2:IDR, 3:Recovery Point SEI
GOPSize : 1 # GOP Size (number of B slice = GOPSize-1)
# Type POC QPoffset QPfactor tcOffsetDiv2 betaOffsetDiv2 temporal_id #ref_pics_active #ref_pics reference pictures
#=========== Motion Search =============
FastSearch : 1 # 0:Full search 1:TZ search
SearchRange : 64 # (0: Search range is a Full frame)
HadamardME : 1 # Use of hadamard measure for fractional ME
FEN : 1 # Fast encoder decision
FDM : 1 # Fast Decision for Merge RD cost
#======== Quantization =============
QP : 37 # Quantization parameter(0-51)
MaxDeltaQP : 0 # CU-based multi-QP optimization
MaxCuDQPSubdiv : 0 # Maximum subdiv for CU luma Qp adjustment
DeltaQpRD : 0 # Slice-based multi-QP optimization
RDOQ : 1 # RDOQ
RDOQTS : 1 # RDOQ for transform skip
#=========== Deblock Filter ============
LoopFilterOffsetInPPS : 1 # Dbl params: 0=varying params in SliceHeader, param = base_param + GOP_offset_param; 1 (default) =constant params in PPS, param = base_param)
LoopFilterDisable : 0 # Disable deblocking filter (0=Filter, 1=No Filter)
LoopFilterBetaOffset_div2 : 0 # base_param: -6 ~ 6
LoopFilterTcOffset_div2 : 0 # base_param: -6 ~ 6
DeblockingFilterMetric : 0 # blockiness metric (automatically configures deblocking parameters in bitstream). Applies slice-level loop filter offsets (LoopFilterOffsetInPPS and LoopFilterDisable must be 0)
#=========== Misc. ============
InternalBitDepth : 10 # codec operating bit-depth
#=========== Coding Tools =================
SAO : 1 # Sample adaptive offset (0: OFF, 1: ON)
TransformSkip : 1 # Transform skipping (0: OFF, 1: ON)
TransformSkipFast : 1 # Fast Transform skipping (0: OFF, 1: ON)
TransformSkipLog2MaxSize : 5
SAOLcuBoundary : 0 # SAOLcuBoundary using non-deblocked pixels (0: OFF, 1: ON)
#============ Slices ================
SliceMode : 0 # 0: Disable all slice options.
# 1: Enforce maximum number of LCU in an slice,
# 2: Enforce maximum number of bytes in an 'slice'
# 3: Enforce maximum number of tiles in a slice
SliceArgument : 1500 # Argument for 'SliceMode'.
# If SliceMode==1 it represents max. SliceGranularity-sized blocks per slice.
# If SliceMode==2 it represents max. bytes per slice.
# If SliceMode==3 it represents max. tiles per slice.
LFCrossSliceBoundaryFlag : 1 # In-loop filtering, including ALF and DB, is across or not across slice boundary.
# 0:not across, 1: across
#============ PCM ================
PCMEnabledFlag : 0 # 0: No PCM mode
PCMLog2MaxSize : 5 # Log2 of maximum PCM block size.
PCMLog2MinSize : 3 # Log2 of minimum PCM block size.
PCMInputBitDepthFlag : 1 # 0: PCM bit-depth is internal bit-depth. 1: PCM bit-depth is input bit-depth.
PCMFilterDisableFlag : 0 # 0: Enable loop filtering on I_PCM samples. 1: Disable loop filtering on I_PCM samples.
#============ Lossless ================
TransquantBypassEnable : 0 # Value of PPS flag.
CUTransquantBypassFlagForce: 0 # Force transquant bypass mode, when transquant_bypass_enable_flag is enabled
#============ VTM settings ======================
LoopFilterTcOffset_div2 : 0
SEIDecodedPictureHash : 0
CbQpOffset : 0
CrQpOffset : 0
SameCQPTablesForAllChroma : 1
QpInValCb : 2 31 43
QpOutValCb : 2 32 41
TemporalSubsampleRatio : 8
ReWriteParamSets : 1
#============ NEXT ====================
# General
CTUSize : 128
LCTUFast : 1
DualITree : 1 # separate partitioning of luma and chroma channels for I-slices
MinQTLumaISlice : 8
MinQTChromaISlice : 4
MinQTNonISlice : 8
MaxBTDepth : 3
MaxBTDepthISliceL : 3
MaxBTDepthISliceC : 3
MTS : 1
MTSIntraMaxCand : 3
MTSInterMaxCand : 4
SBT : 1
LFNST : 1
ISP : 1
Affine : 1
SubPuMvp : 1
MaxNumMergeCand : 6
LMChroma : 1 # use CCLM only
DepQuant : 1
IMV : 1
ALF : 1
IBC : 0 # turned off in CTC
AllowDisFracMMVD : 1
AffineAmvr : 0
LMCSEnable : 1 # LMCS: 0: disable, 1:enable
LMCSSignalType : 0 # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG
LMCSUpdateCtrl : 1 # LMCS model update control: 0:RA, 1:AI, 2:LDB/LDP
MIP : 1
JointCbCr : 1 # joint coding of chroma residuals (if available): 0: disable, 1: enable
# Fast tools
PBIntraFast : 1
ISPFast : 1
FastMrg : 1
AMaxBT : 1
FastMIP : 1
FastLFNST : 1
# Encoder optimization tools
AffineAmvrEncOpt : 0
### DO NOT ADD ANYTHING BELOW THIS LINE ###
### DO NOT DELETE THE EMPTY LINE BELOW ###
这里有一些参数需要去修改:
① InputFile:是你存放测试序列的路径,我这里用的是C序列的BasketballDrill序列。
② FramesToBeEncoded:指的是这个测试总共编码的帧数,这里测试只需要设置为40帧。
③ QP:指的是当前序列是在什么量化参数下进行编码,这里本地测试只需要设置为37,这样编码速度最快。
④TemporalSubsampleRatio:指的是编码帧间隔,每间隔多少帧编一帧,AI的通用默认值为8,这里本地测试就为默认值就OK,最终本地测试需要编码的总帧数就是40/8=5帧.
注意:其余参数不要动!
保存完毕之后我们本地的cfg文件就算配置好了。
二、在配置好cfg文件之后,就需要开始具体测试编码的步骤如下:
第一步:生成编解码的.exe文件。
①首先,如果你修改好了一版自己的VTM代码,则先在Release条件下,在生成中选择->清理解决方案;
显示清理成功。
②再选择->重新生成解决方案。然后静静等待
③此时到VTM参考软件的对应的目录:D:\VVCSoftware_VTM-VTM-6.0\bin\vs15\msvc-19.10\x86_64\release中去将两个exe文件拷贝出来,该课执行文件就是将VTM的代码全部打包成一个exe方便在外界执行。
第二步:
①在某个地方自己新建一个文件夹,文件夹的名字最好改成你修改的方案的名字(这里用Test代替),然后将第一步生成好的两个exe可执行文件复制到该新建的文件夹中,如下图所示:
这里第一行首先执行编码的.exe文件,然后读取相对应VTM文件目录下的cfg文件,进行编码的进程,最后输出编码数据到txt文件中。
第二行首先执行解码的.exe文件,然后解析编码后的二进制码流(bin文件)。最后输出解码后的重建YUV.
这里需要注意的是:-c 表示编码指令,-b表示解码指令,-o表示输出指令
第三步:
运行test.bat文件,就开始执行编解码的操作,执行如下界面所示,如果没有出现突然结束的现象就说明运行正确,一般会持续几分钟,根据电脑性能会有所差异,但不会很快:
运行以后,会生成编码端的重建YUV文件(rec37.yuv)+编码码流文件(str37.bin)+输出日志文件(Enc_Out.txt,记录编码性能以及时间)
第四步:
静静等待编解码结束,然后会得到完整的编码后的重建YUV以及解码后的重建YUV,如下图所示:
第五步:
用BeyondCompare这款软件去比较dec.yuv和rec37.yuv是否编解码一致,如果一致,说明测试方案正确无误。直到这一步,才能最终确定自己的测试方案是否是正确的。比较后一致的效果图如下,显示二进制相同,如果二进制不同,则说明自己的测试方案有误,一般都是代码写的有问题,那就回去再好好调试调试代码叭~
第六步:
检查编码性能,打开日志文件Enc_Out.txt。里面记录了每一帧的码率、以及各YUV三个分量的PSNR指标,最后还有平均性能指标(下图红线圈起来的)。将自己测试方案的性能和Anchor的性能相比较,如果码率上升并且PSRN降低,大致说明你的测试方案性能凉了;反之,说明性能良好。但是如果码率下降,PSNR也降低或者码率升高,PSNR也升高,则就不好判断性能好坏,因此需要在远程计算机上测试小序列(C、D)的全帧(注意是小序列,没必要大序列都测,除非小序列性能特别好,才有资本测大序列)。当然也不能全信5帧的测试结果,有时候5帧也不太准,但是大部分情况还是可以大致反映总体性能~
一、首选需要会连接实验室的远程计算机资源,.8或者.9,.8的处理器好点,跑程序快。如果.8不够用的话,可以在.9上测试小序列。远程计算机连接顺序如下:
①首先在开始菜单栏中找到远程桌面连接
②然后选择.8或者.9(关于这个链接的密码和用户名实验室的同学可以直接问我,因为是内部人员使用,这里不方便透露)
③登录远程之后如下所示:
二、登录远程之后,就可以在远程计算机上配置所有序列的cfg文件了,不过目前远程计算机上的cfg都是已经配置好的,可以直接用,这里我只给出具体使用的方法(如果想具体了解怎么配置,可以直接问我,其实和在本地计算机上配置方法差不多,只不过稍微麻烦一点)。使用步骤如下:
第一步:
首选找一个空余的磁盘,然后新建一个文件夹Test(一般新建在实验室的通用路径下F:\205\rqh\VTM 6.0\Test。rqh是我的名字缩写,你自己的文件夹就按照自己的名字缩写命名就好),用于测试自己方案的全帧序列(我这里只给出AI全帧的测试,RA,LD的测试同上),然后把在自己本地计算机上生成好的编码可执行文件EncoderApp.exe拷贝到远程计算机上的Test文件夹。
第二步:
然后将E:\VTM6.0_Test-8\bat\AllIntra_frames路径下的A1、A2、B、C、D、E、F(每个文件夹下面都有各自序列的子文件夹)文件夹考到自己的Test文件夹中,如下所示:
第三步:
将EncoderApp.exe拷贝到每一个序列的文件夹中,这里拿campfire序列举例子:
第四步:
运行所有的批处理文件,这个操作就和本地测试时候的操作一样,运行之后,就开始了全帧的漫长编码之旅:
第五步:
等所有序列都跑完了,就可以开始录数据了,录数据可以直接用一个Python脚本文件一键生成,还是在E:\VTM6.0_Test-8\bat\AllIntra_frames路径下,有一个Python文件如下:
第六步:
将该Python文件拷贝到自己的Test文件夹下,然后点击运行即可,就会将所有序列的数据统计到一个summary.txt文件中,如下所示。
第七步:
将上面统计好的数据复制到VTM的数据表格中即可,如下图所示(左边放Anchor数据,右边是自己的测试数据)。