關於初學視頻編碼的同學來講,除了瞭解關於視頻編碼的一些理論的知識以及代碼之外,還有一項必備的技能就是能夠在各種操作系統之下,熟練的去跑視頻編解碼的代碼,以及怎麼配置相關的配置文件,如何將編解碼之後的數據統計出來都是要求必須熟練掌握的。今天詳細講一下關於在本地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數據,右邊是自己的測試數據)。