blob: 781e6ff1aca88f07c8e16849cafeb117c20ac0a2 [file] [log] [blame] [edit]
#!/usr/bin/env python
## Copyright (c) 2021, Alliance for Open Media. All rights reserved
##
## This source code is subject to the terms of the BSD 3-Clause Clear License and the
## Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear License was
## not distributed with this source code in the LICENSE file, you can obtain it
## at aomedia.org/license/software-license/bsd-3-c-c/. If the Alliance for Open Media Patent
## License 1.0 was not distributed with this source code in the PATENTS file, you
## can obtain it at aomedia.org/license/patent-license/.
##
__author__ = "maggie.sun@intel.com, ryanlei@meta.com"
import os
import sys
import argparse
import subprocess
from EncDecUpscale import Run_EncDec_Upscale, GetBsReconFileName, Encode, GetBitstreamFile, Decode
from VideoScaler import GetDownScaledOutFile, DownScaling, UpScaling
from CalculateQualityMetrics import CalculateQualityMetric, GatherQualityMetrics
from Utils import GetShortContentName, CreateNewSubfolder, SetupLogging, \
Cleanfolder, CreateClipList, Clip, GatherPerfInfo, GetEncLogFile, GetDecLogFile, \
GetRDResultCsvFile, GatherPerframeStat, GatherInstrCycleInfo, ParseDecLogFile, \
Interpolate_Bilinear, Interpolate_PCHIP, convex_hull, DeleteFile, md5, get_total_frame
from ScalingTest import Run_Scaling_Test
from Config import LogLevels, QPs, QualityList, WorkPath, \
Path_RDResults, DnScalingAlgos, UpScalingAlgos, \
EncodeMethods, CodecNames, LoggerName, DnScaleRatio, \
EnablePreInterpolation, AS_DOWNSCALE_ON_THE_FLY,\
UsePerfUtil, ScaleMethods, EnableTimingInfo, InterpolatePieces, EnableMD5, \
UsePCHIPInterpolation, EnableParallelGopEncoding, GOP_SIZE
from CalcQtyWithVmafTool import GetVMAFLogFile
import Utils
###############################################################################
##### Helper Functions ########################################################
def setupWorkFolderStructure():
global Path_Bitstreams, Path_DecodedYuv, Path_UpScaleYuv, Path_DnScaleYuv, \
Path_QualityLog, Path_TestLog, Path_CfgFiles, Path_DecUpScaleYuv, Path_PerfLog, \
Path_EncLog, Path_DecLog, Path_VmafLog, Path_CmdLog
Path_Bitstreams = CreateNewSubfolder(WorkPath, "bitstreams")
Path_DecodedYuv = CreateNewSubfolder(WorkPath, "decodedYUVs")
Path_UpScaleYuv = CreateNewSubfolder(WorkPath, "upscaledYUVs")
Path_DecUpScaleYuv = CreateNewSubfolder(WorkPath, "decUpscaledYUVs")
Path_DnScaleYuv = CreateNewSubfolder(WorkPath, "downscaledYUVs")
Path_QualityLog = CreateNewSubfolder(WorkPath, "qualityLogs")
Path_TestLog = CreateNewSubfolder(WorkPath, "testLogs")
Path_CfgFiles = CreateNewSubfolder(WorkPath, "configFiles")
Path_PerfLog = CreateNewSubfolder(WorkPath, "perfLogs")
Path_EncLog = CreateNewSubfolder(WorkPath, "encLogs")
Path_DecLog = CreateNewSubfolder(WorkPath, "decLogs")
Path_CmdLog = CreateNewSubfolder(WorkPath, "cmdLogs")
Path_VmafLog = CreateNewSubfolder(WorkPath, "vmafLogs")
###############################################################################
######### Major Functions #####################################################
def CleanUp_workfolders():
folders = [Path_DnScaleYuv, Path_Bitstreams, Path_DecodedYuv, Path_QualityLog,
Path_TestLog, Path_CfgFiles, Path_PerfLog, Path_EncLog, Path_DecLog,
Path_VmafLog]
if not KeepUpscaledOutput:
folders += [Path_UpScaleYuv, Path_DecUpScaleYuv]
for folder in folders:
Cleanfolder(folder)
def Run_ConvexHull_Test(clip, dnScalAlgo, upScalAlgo, ScaleMethod, LogCmdOnly = False):
Utils.Logger.info("start encode %s" % clip.file_name)
DnScaledRes = [(int(clip.width / ratio), int(clip.height / ratio)) for ratio in
DnScaleRatio]
total_frame = get_total_frame('AS', clip)
for i in range(len(DnScaledRes)):
DnScaledW = DnScaledRes[i][0]
DnScaledH = DnScaledRes[i][1]
# downscaling if the downscaled file does not exist
dnscalyuv = GetDownScaledOutFile(clip, DnScaledW, DnScaledH, Path_DnScaleYuv,
ScaleMethod, dnScalAlgo, AS_DOWNSCALE_ON_THE_FLY, i)
if not os.path.isfile(dnscalyuv):
dnscalyuv = DownScaling(ScaleMethod, clip, total_frame, DnScaledW, DnScaledH,
Path_DnScaleYuv, Path_CfgFiles, dnScalAlgo, LogCmdOnly)
ds_clip = Clip(GetShortContentName(dnscalyuv, False)+'.y4m', dnscalyuv,
clip.file_class, DnScaledW, DnScaledH, clip.fmt, clip.fps_num,
clip.fps_denom, clip.bit_depth)
QPSet = QPs['AS']
for QP in QPSet:
Utils.Logger.info("start encode and upscale for QP %d" % QP)
JobName = '%s_%s_%s_%s_%dx%d_Preset_%s_QP_%d' % \
(GetShortContentName(clip.file_name, False),
EncodeMethod, CodecName, "AS", DnScaledW, DnScaledH, EncodePreset, QP)
if LogCmdOnly:
Utils.CmdLogger.write("============== %s Job Start =================\n" % JobName)
#encode and upscaling
reconyuv = Run_EncDec_Upscale(EncodeMethod, CodecName, EncodePreset,
ds_clip, 'AS', QP, total_frame,
clip.width, clip.height, Path_Bitstreams,
Path_DecodedYuv, Path_DecUpScaleYuv,
Path_CfgFiles, Path_PerfLog, Path_EncLog, Path_DecLog,
upScalAlgo, ScaleMethod, SaveMemory, LogCmdOnly)
#calcualte quality distortion
Utils.Logger.info("start quality metric calculation")
CalculateQualityMetric(clip.file_path, total_frame, reconyuv,
clip.fmt, clip.width, clip.height,
clip.bit_depth, Path_QualityLog, Path_VmafLog, LogCmdOnly)
if SaveMemory:
DeleteFile(reconyuv, LogCmdOnly)
if LogCmdOnly:
Utils.CmdLogger.write("============== %s Job End =================\n" % JobName)
if SaveMemory:
if AS_DOWNSCALE_ON_THE_FLY and dnscalyuv != clip.file_path:
DeleteFile(dnscalyuv)
Utils.Logger.info("finish running encode test.")
Utils.Logger.info("finish running encode test.")
def Run_Parallel_ConvexHull_Test(clip, dnScalAlgo, upScalAlgo, ScaleMethod, LogCmdOnly = False):
if EnableParallelGopEncoding:
Utils.Logger.info("start encode %s" % clip.file_name)
DnScaledRes = [(int(clip.width / ratio), int(clip.height / ratio)) for ratio in
DnScaleRatio]
total_frame = get_total_frame('AS', clip)
for i in range(len(DnScaledRes)):
DnScaledW = DnScaledRes[i][0]
DnScaledH = DnScaledRes[i][1]
# downscaling if the downscaled file does not exist
dnscalyuv = GetDownScaledOutFile(clip, DnScaledW, DnScaledH, Path_DnScaleYuv,
ScaleMethod, dnScalAlgo, AS_DOWNSCALE_ON_THE_FLY, i)
if not os.path.isfile(dnscalyuv):
dnscalyuv = DownScaling(ScaleMethod, clip, total_frame, DnScaledW, DnScaledH,
Path_DnScaleYuv, Path_CfgFiles, dnScalAlgo, LogCmdOnly)
ds_clip = Clip(GetShortContentName(dnscalyuv, False)+'.y4m', dnscalyuv,
clip.file_class, DnScaledW, DnScaledH, clip.fmt, clip.fps_num,
clip.fps_denom, clip.bit_depth)
QPSet = QPs['AS']
for QP in QPSet:
Utils.Logger.info("start encode for QP %d" % QP)
total_frame = get_total_frame('AS', clip)
# Encode
start_frame = 0
while start_frame < total_frame:
#encode
num_frames = GOP_SIZE
if (start_frame + num_frames) > total_frame:
num_frames = total_frame - start_frame
JobName = '%s_%s_%s_%s_%dx%d_Preset_%s_QP_%d_start_%d_frames_%d' % \
(GetShortContentName(clip.file_name, False),
EncodeMethod, CodecName, "AS", DnScaledW, DnScaledH,
EncodePreset, QP, start_frame, num_frames)
if LogCmdOnly:
Utils.CmdLogger.write("============== %s Job Start =================\n"%JobName)
#encode
bsFile = Encode(EncodeMethod, CodecName, EncodePreset, ds_clip, 'AS', QP,
num_frames, Path_Bitstreams, Path_PerfLog,
Path_EncLog, start_frame, LogCmdOnly)
start_frame += num_frames
if LogCmdOnly:
Utils.CmdLogger.write("============== %s Job End =================\n" % JobName)
if SaveMemory:
if AS_DOWNSCALE_ON_THE_FLY and dnscalyuv != clip.file_path:
DeleteFile(dnscalyuv)
Utils.Logger.info("finish running encode test.")
Utils.Logger.info("finish running encode test.")
else:
Utils.Logger.error("parallel encode function can only be used with Parallel Gop Encoding mode")
def SaveConvexHullResults(content, ScaleMethod, dnScAlgos, upScAlgos, csv, perframe_csv,
EnablePreInterpolation=False):
Utils.Logger.info("start saving RD results to excel file.......")
missing = open("AS_Missing.log", 'wt')
if not os.path.exists(Path_RDResults):
os.makedirs(Path_RDResults)
QPSet = QPs['AS']
total_frames = get_total_frame('AS', clip)
DnScaledRes = [(int(clip.width / ratio), int(clip.height / ratio))
for ratio in DnScaleRatio]
contentname = GetShortContentName(clip.file_name)
for indx in list(range(len(dnScAlgos))):
# write RD data
for i in range(len(DnScaledRes)):
DnScaledW = DnScaledRes[i][0]
DnScaledH = DnScaledRes[i][1]
bitratesKbps = []; qualities = []
for qp in QPSet:
bs, reconyuv = GetBsReconFileName(EncodeMethod, CodecName, 'AS',
EncodePreset, clip, DnScaledW,
DnScaledH, ScaleMethod, dnScAlgos[indx],
upScAlgos[indx], qp, 0, total_frames,
Path_Bitstreams, False, i)
if not os.path.exists(bs):
print("bitstream %s is missing" % bs)
missing.write("\nbitstream %s is missing" % bs)
continue
dec_log = GetDecLogFile(bs, Path_DecLog)
if not os.path.exists(dec_log):
print("dec_log %s is missing" % dec_log)
missing.write("\ndec_log %s is missing" % dec_log)
continue
num_dec_frames = ParseDecLogFile(dec_log)
if num_dec_frames == 0:
print("decoding error in %s" % dec_log)
missing.write("\ndecoding error in %s" % dec_log)
continue
vmaf_log = GetVMAFLogFile(reconyuv, Path_QualityLog)
if not os.path.exists(vmaf_log):
print("vmaf_log %s is missing" % vmaf_log)
missing.write("\nvmaf_log %s is missing" % vmaf_log)
continue
quality, perframe_vmaf_log, frame_num = GatherQualityMetrics(reconyuv, Path_QualityLog)
if not quality:
print("%s quality metrics is missing" % bs)
missing.write("\n%s quality metrics is missing" % bs)
continue
bitrate = round((os.path.getsize(bs) * 8 * (clip.fps_num / clip.fps_denom)
/ frame_num) / 1000.0, 6)
bitratesKbps.append(bitrate)
qualities.append(quality)
#"TestCfg,EncodeMethod,CodecName,EncodePreset,Class,OrigRes,Name,FPS,BitDepth,CodedRes,QP,Bitrate(kbps)")
csv.write("%s,%s,%s,%s,%s,%s,%s,%.4f,%d,%s,%d,%f"%
("AS", EncodeMethod, CodecName, EncodePreset, clip.file_class,contentname,
str(clip.width)+"x"+str(clip.height), clip.fps,clip.bit_depth,
str(DnScaledW)+"x"+str(DnScaledH),qp,bitrate))
for qty in quality:
csv.write(",%f"%qty)
if EnableTimingInfo and not EnableParallelGopEncoding:
if UsePerfUtil:
enc_time, dec_time, enc_instr, dec_instr, enc_cycles, dec_cycles = GatherInstrCycleInfo(bs, Path_PerfLog)
csv.write(",%.2f,%.2f,%s,%s,%s,%s,"%(enc_time,dec_time,enc_instr,dec_instr,enc_cycles,dec_cycles))
else:
enc_time, dec_time = GatherPerfInfo(bs, Path_PerfLog)
csv.write(",%.2f,%.2f," % (enc_time, dec_time))
else:
csv.write(",,,,,,,")
if EnableMD5:
enc_md5 = md5(bs)
dec_md5 = md5(reconyuv)
csv.write("%s,%s" % (enc_md5, dec_md5))
csv.write("\n")
if (EncodeMethod == 'aom') and not EnableParallelGopEncoding:
enc_log = GetEncLogFile(bs, Path_EncLog)
GatherPerframeStat("AS", EncodeMethod, CodecName, EncodePreset, clip, GetShortContentName(bs),
DnScaledW, DnScaledH, qp, enc_log, perframe_csv,
perframe_vmaf_log)
missing.close()
Utils.Logger.info("finish export convex hull results to excel file.")
def Run_AS_Concatenate_Test(test_cfg, clip, dnScalAlgo, codec, method, preset, LogCmdOnly = False):
if EnableParallelGopEncoding:
Utils.Logger.info("start running %s concatenate tests with %s"
% (test_cfg, clip.file_name))
DnScaledRes = [(int(clip.width / ratio), int(clip.height / ratio)) for ratio in
DnScaleRatio]
for i in range(len(DnScaledRes)):
DnScaledW = DnScaledRes[i][0]
DnScaledH = DnScaledRes[i][1]
# downscaling if the downscaled file does not exist
dnscalyuv = GetDownScaledOutFile(clip, DnScaledW, DnScaledH, Path_DnScaleYuv,
ScaleMethod, dnScalAlgo, AS_DOWNSCALE_ON_THE_FLY, i)
ds_clip = Clip(GetShortContentName(dnscalyuv, False)+'.y4m', dnscalyuv,
clip.file_class, DnScaledW, DnScaledH, clip.fmt, clip.fps_num,
clip.fps_denom, clip.bit_depth)
QPSet = QPs['AS']
for QP in QPSet:
Utils.Logger.info("start encode for QP %d" % QP)
total_frame = get_total_frame('AS', clip)
cmd = "cat "
start_frame = 0
while start_frame < total_frame:
num_frames = GOP_SIZE
if (start_frame + num_frames) > total_frame:
num_frames = total_frame - start_frame
bsfile = GetBitstreamFile(method, codec, test_cfg, preset, ds_clip.file_path,
QP, start_frame, num_frames, Path_Bitstreams)
cmd += " %s " % bsfile
start_frame += num_frames
bsfile = '%s_%s_%s_%s_Preset_%s_QP_%d_start_%d_frames_%d.obu' % \
(GetShortContentName(ds_clip.file_name, False),
method, codec, test_cfg, preset, QP, 0, total_frame)
cmd += " > %s/%s" % (Path_Bitstreams, bsfile)
if LogCmdOnly:
Utils.CmdLogger.write("%s\n" % cmd)
else:
subprocess.call(cmd, shell=True)
def Run_AS_Decode_Test(test_cfg, clip, dnScalAlgo, upScalAlgo, scale_method, codec, method, preset, LogCmdOnly = False):
if EnableParallelGopEncoding:
Utils.Logger.info("start running %s decode tests with %s"
% (test_cfg, clip.file_name))
DnScaledRes = [(int(clip.width / ratio), int(clip.height / ratio)) for ratio in
DnScaleRatio]
for i in range(len(DnScaledRes)):
DnScaledW = DnScaledRes[i][0]
DnScaledH = DnScaledRes[i][1]
# downscaling if the downscaled file does not exist
dnscalyuv = GetDownScaledOutFile(clip, DnScaledW, DnScaledH, Path_DnScaleYuv,
ScaleMethod, dnScalAlgo, AS_DOWNSCALE_ON_THE_FLY, i)
ds_clip = Clip(GetShortContentName(dnscalyuv, False)+'.y4m', dnscalyuv,
clip.file_class, DnScaledW, DnScaledH, clip.fmt, clip.fps_num,
clip.fps_denom, clip.bit_depth)
QPSet = QPs[test_cfg]
for QP in QPSet:
Utils.Logger.info("start decode with QP %d" % (QP))
total_frame = get_total_frame(test_cfg, clip.file_name)
# decode
JobName = '%s_%s_%s_%s_Preset_%s_QP_%d' % \
(GetShortContentName(ds_clip.file_name, False),
method, codec, test_cfg, preset, QP)
if LogCmdOnly:
Utils.CmdLogger.write("============== %s Job Start =================\n"%JobName)
bsfile = '%s/%s_%s_%s_%s_Preset_%s_QP_%d_start_%d_frames_%d.obu' % \
(Path_Bitstreams, GetShortContentName(ds_clip.file_name, False),
method, codec, test_cfg, preset, QP, 0, total_frame)
decodedYUV = Decode(ds_clip, method, test_cfg, codec, bsfile, Path_DecodedYuv, Path_PerfLog, False,
Path_DecLog, LogCmdOnly)
dec_clip = Clip(GetShortContentName(decodedYUV, False) + ".y4m",
decodedYUV, ds_clip.file_class, ds_clip.width, ds_clip.height,
ds_clip.fmt, 0, 0, ds_clip.bit_depth)
upscaledYUV = UpScaling(scale_method, dec_clip, total_frame, clip.width, clip.height,
Path_UpScaleYuv, Path_CfgFiles, upScalAlgo, LogCmdOnly)
if SaveMemory and decodedYUV != upscaledYUV:
DeleteFile(decodedYUV, LogCmdOnly)
#calcualte quality distortion
Utils.Logger.info("start quality metric calculation")
CalculateQualityMetric(clip.file_path, total_frame, upscaledYUV,
clip.fmt, clip.width, clip.height,
clip.bit_depth, Path_QualityLog, Path_VmafLog, LogCmdOnly)
if SaveMemory:
DeleteFile(upscaledYUV, LogCmdOnly)
if LogCmdOnly:
Utils.CmdLogger.write("============== %s Job End =================\n" % JobName)
else:
Utils.Logger.error("decode function can only be used with Parallel Gop Encoding mode")
def ParseArguments(raw_args):
parser = argparse.ArgumentParser(prog='ConvexHullTest.py',
usage='%(prog)s [options]',
description='')
parser.add_argument('-f', '--function', dest='Function', type=str,
required=True, metavar='',
choices=["clean", "scaling","encode",
"convexhull", "concatnate", "decode"],
help="function to run: clean, scaling, encode,"
" convexhull, concatnate, decode")
parser.add_argument('-k', "--KeepUpscaleOutput", dest='KeepUpscaledOutput',
type=bool, default=False, metavar='',
help="in function clean, if keep upscaled yuv files. It"
" is false by default")
parser.add_argument('-s', "--SaveMemory", dest='SaveMemory', type=bool,
default=True, metavar='',
help="save memory mode will delete most files in"
" intermediate steps and keeps only necessary "
"ones for RD calculation. It is false by default")
parser.add_argument('-CmdOnly', "--LogCmdOnly", dest='LogCmdOnly', type=bool,
default=False, metavar='',
help="LogCmdOnly mode will only capture the command sequences"
"It is false by default")
parser.add_argument('-l', "--LoggingLevel", dest='LogLevel', type=int,
default=3, choices=range(len(LogLevels)), metavar='',
help="logging level: 0:No Logging, 1: Critical, 2: Error,"
" 3: Warning, 4: Info, 5: Debug")
parser.add_argument('-c', "--CodecName", dest='CodecName', type=str,
choices=CodecNames, metavar='',
help="CodecName: av1, av2")
parser.add_argument('-m', "--EncodeMethod", dest='EncodeMethod', type=str,
choices=EncodeMethods, metavar='',
help="EncodeMethod: aom, svt")
parser.add_argument('-p', "--EncodePreset", dest='EncodePreset', type=str,
metavar='', help="EncodePreset: 0,1,2... for aom and svt")
parser.add_argument('-t', '--ScaleMethod', dest='ScaleMethod', type=str,
choices=ScaleMethods, metavar='',
help="ScaleMethod: ffmpeg, hdrtool, aom")
if len(raw_args) == 1:
parser.print_help()
sys.exit(1)
args = parser.parse_args(raw_args[1:])
global Function, KeepUpscaledOutput, SaveMemory, LogLevel, CodecName,\
EncodeMethod, ScaleMethod, EncodePreset, LogCmdOnly
Function = args.Function
KeepUpscaledOutput = args.KeepUpscaledOutput
SaveMemory = args.SaveMemory
LogLevel = args.LogLevel
CodecName = args.CodecName
EncodeMethod = args.EncodeMethod
ScaleMethod = args.ScaleMethod
EncodePreset = args.EncodePreset
LogCmdOnly = args.LogCmdOnly
######################################
# main
######################################
if __name__ == "__main__":
#sys.argv = ["","-f","clean"]
#sys.argv = ["","-f","scaling", "-t", "hdrtool"]
#sys.argv = ["", "-f", "sumscaling", "-t", "hdrtool"]
#sys.argv = ["", "-f", "encode","-c","av2","-m","aom","-p","6", "-t", "hdrtool"]
#sys.argv = ["", "-f", "convexhull","-c","av2","-m","aom","-p","0", "-t", "hdrtool"]
#sys.argv = ["", "-f", "summary", "-c", "av2", "-m", "aom", "-p", "0", "-t", "hdrtool"]
ParseArguments(sys.argv)
# preparation for executing functions
setupWorkFolderStructure()
if Function != 'clean':
SetupLogging(LogLevel, LogCmdOnly, LoggerName, WorkPath, Path_TestLog)
clip_list = CreateClipList('AS')
# execute functions
if Function == 'clean':
CleanUp_workfolders()
elif Function == 'scaling':
for clip in clip_list:
for dnScaleAlgo, upScaleAlgo in zip(DnScalingAlgos, UpScalingAlgos):
Run_Scaling_Test(clip, dnScaleAlgo, upScaleAlgo,
Path_DnScaleYuv, Path_UpScaleYuv, Path_QualityLog,
Path_CfgFiles, SaveMemory, KeepUpscaledOutput, ScaleMethod,
LogCmdOnly)
if SaveMemory:
Cleanfolder(Path_DnScaleYuv)
if not KeepUpscaledOutput:
Cleanfolder(Path_UpScaleYuv)
elif Function == 'encode':
for clip in clip_list:
for dnScalAlgo, upScalAlgo in zip(DnScalingAlgos, UpScalingAlgos):
if EnableParallelGopEncoding:
Run_Parallel_ConvexHull_Test(clip, dnScalAlgo, upScalAlgo, ScaleMethod, LogCmdOnly)
else:
Run_ConvexHull_Test(clip, dnScalAlgo, upScalAlgo, ScaleMethod, LogCmdOnly)
if SaveMemory:
Cleanfolder(Path_DnScaleYuv)
if not KeepUpscaledOutput:
Cleanfolder(Path_UpScaleYuv)
elif Function == 'decode':
test_cfg = "AS"
if EnableParallelGopEncoding:
clip_list = CreateClipList(test_cfg)
for clip in clip_list:
for dnScalAlgo, upScalAlgo in zip(DnScalingAlgos, UpScalingAlgos):
if EnableParallelGopEncoding:
Run_AS_Decode_Test(test_cfg, clip, dnScalAlgo, upScalAlgo, ScaleMethod, CodecName, EncodeMethod, EncodePreset, LogCmdOnly)
else:
Utils.Logger.error("concatenate function can only be used with Parallel Gop Encoding mode and RA configuration")
else:
print("decode command can only be used when parallel gop encoding is enabled")
elif Function == 'concatnate':
test_cfg = "AS"
if EnableParallelGopEncoding:
clip_list = CreateClipList(test_cfg)
for clip in clip_list:
for dnScalAlgo, upScalAlgo in zip(DnScalingAlgos, UpScalingAlgos):
if EnableParallelGopEncoding:
Run_AS_Concatenate_Test(test_cfg, clip, dnScalAlgo, CodecName, EncodeMethod, EncodePreset, LogCmdOnly)
else:
Utils.Logger.error("concatenate function can only be used with Parallel Gop Encoding mode and RA configuration")
else:
print("concatnate command can only be used when parallel gop encoding is enabled")
elif Function == 'convexhull':
csv_file, perframe_csvfile = GetRDResultCsvFile(EncodeMethod, CodecName, EncodePreset, "AS")
csv = open(csv_file, "wt")
csv.write("TestCfg,EncodeMethod,CodecName,EncodePreset,Class,Name,OrigRes,FPS," \
"BitDepth,CodedRes,QP,Bitrate(kbps)")
for qty in QualityList:
csv.write(',' + qty)
csv.write(",EncT[s],DecT[s]")
if UsePerfUtil:
csv.write(",EncInstr,DecInstr,EncCycles,DecCycles")
if EnableMD5:
csv.write(",EncMD5,DecMD5")
csv.write("\n")
perframe_csv = open(perframe_csvfile, 'wt')
perframe_csv.write("TestCfg,EncodeMethod,CodecName,EncodePreset,Class,Name,Res,FPS," \
"BitDepth,QP,POC,FrameType,Level,qindex,FrameSize")
for qty in QualityList:
if not qty.startswith("APSNR"):
perframe_csv.write(',' + qty)
perframe_csv.write('\n')
for clip in clip_list:
SaveConvexHullResults(clip, ScaleMethod, DnScalingAlgos, UpScalingAlgos, csv, perframe_csv,
EnablePreInterpolation)
csv.close()
perframe_csv.close()
else:
Utils.Logger.error("invalid parameter value of Function")