From 7bff99a6c77449c5bcbe8421cb94e5bdd8022c97 Mon Sep 17 00:00:00 2001 From: Artur Mukhamadiev Date: Sat, 11 Oct 2025 23:15:53 +0300 Subject: [PATCH] [autotest] config moved to .yaml file :Release Notes: added PyYAML dep :Detailed Notes: - :Testing Performed: - :QA Notes: - :Issues Addressed: - --- autotest-conf.yaml | 68 ++++++++++++++++++++++++++ autotestConfig.py | 62 ++++++++++++++++++++++++ gstreamerAutotest.py | 112 +++++++++++-------------------------------- requirements.txt | 1 + 4 files changed, 158 insertions(+), 85 deletions(-) create mode 100644 autotest-conf.yaml create mode 100644 autotestConfig.py diff --git a/autotest-conf.yaml b/autotest-conf.yaml new file mode 100644 index 0000000..e5a6eec --- /dev/null +++ b/autotest-conf.yaml @@ -0,0 +1,68 @@ +repeats: 3 + +options: + x264enc: + bitrate: [ "10000", "20000", "5000" ] + speed-preset: [ "ultrafast", "fast", "medium" ] + tune: [ "zerolatency" ] + sliced-threads: [ "true", "false" ] + b-adapt: [ "true", "false" ] + rc-lookahead: [ "40", "0" ] + ref: [ "3", "0" ] + nvh264enc: + bitrate: [ "10000", "20000", "5000" ] + preset: [ "4", "5", "1" ] + rc-lookahead: [ "0" ] + rc-mode: [ "2", "0", "5" ] + zerolatency: [ "true", "false" ] + nvv4l2h264enc: + bitrate: [ "10000000", "20000000", "5000000" ] + profile: [ "0", "1", "2" ] + preset-id: [ "1", "2", "3" ] + control-rate: [ "1", "2" ] + idrinterval: [ "1", "256" ] + tuning-info-id: [ "4", "2", "3" ] + +videos: + base-daVinci: "./test.yuv" + +testsource: "videotestsrc pattern=smpte" + +videosrc: + raw: ["filesrc location=", " ! rawvideoparse "] + h264: ["filesrc location=", " ! decodebin"] + +psnr_check: + x264enc: "-pixel_format yuv420p -color_range pc" + nvh264enc: "-pixel_format nv12 -color_range tv" + nvv4l2h264enc: "-pixel_format nv12 -color_range tv" + +with_docker: + - nvv4l2h264enc + +formats: + x264enc: "I420" + nvh264enc: "NV12" + nvv4l2h264enc: "NV12" + +profiles: + - baseline + - main + +videoconvert: + nvv4l2h264enc: "nvvideoconvert" + nvh264enc: "videoconvert" + x264enc: "videoconvert" + +video_info: + video1: "-video_size 1920x1080 -framerate 23.98" + sample-surgery: "-video_size 1280x720 -framerate 29.97" + base-daVinci: "-video_size 1280x720 -framerate 59.94" + +gst_video_info: + video1: "format=I420,height=1080,width=1920,framerate=24000/1001" + base-daVinci: "format=2 height=720 width=1280 colorimetry=bt601 framerate=60000/1001" + +latency_filename: "latency-traces-autotest.log" + +docker_run_string: "sudo -S docker container exec deepstream-gst bash" \ No newline at end of file diff --git a/autotestConfig.py b/autotestConfig.py new file mode 100644 index 0000000..890f23d --- /dev/null +++ b/autotestConfig.py @@ -0,0 +1,62 @@ +import yaml + +class AutotestConfig: + def __init__(self, path='autotest-conf.yaml'): + with open(path, 'r') as file: + self.data = yaml.safe_load(file) + + @property + def options(self): + return self.data["options"] + + @property + def videos(self): + return self.data["videos"] + + @property + def testsource(self): + return self.data["testsource"] + + @property + def videosrc(self): + return self.data["videosrc"] + + @property + def psnr_check(self): + return self.data.get("psnr_check", {}) + + @property + def with_docker(self): + return self.data.get("with_docker", []) + + @property + def repeats(self): + return self.data.get("repeats") + + @property + def formats(self): + return self.data.get("formats", {}) + + @property + def profiles(self): + return self.data.get("profiles", []) + + @property + def videoconvert(self): + return self.data.get("videoconvert", {}) + + @property + def video_info(self): + return self.data.get("video_info", {}) + + @property + def gst_video_info(self): + return self.data.get("gst_video_info", {}) + + @property + def latency_filename(self): + return self.data.get("latency_filename") + + @property + def docker_run_string(self): + return self.data["docker_run_string"] \ No newline at end of file diff --git a/gstreamerAutotest.py b/gstreamerAutotest.py index 094f001..6bcadc6 100644 --- a/gstreamerAutotest.py +++ b/gstreamerAutotest.py @@ -5,80 +5,18 @@ from latencyParse import getLatencyTable import os, stat, subprocess import pandas as pd from extra import log_args_decorator +from autotestConfig import AutotestConfig +import logging -options = { - "x264enc": { - "bitrate": ["10000", "20000", "5000"], - "speed-preset": ["ultrafast", "fast", "medium"], - "tune": ["zerolatency"], - "sliced-threads": ["true", "false"], - "b-adapt": ["true", "false"], - "rc-lookahead": ["40", "0"], - "ref": ["3", "0"] - }, - "nvh264enc": { - "bitrate": ["10000", "20000", "5000"], - "preset": ["4", "5", "1"], - "rc-lookahead": ["0"], - "rc-mode": ["2", "0", "5"], - "zerolatency": ["true", "false"], - }, - "nvv4l2h264enc": { - "bitrate": ["10000000", "20000000", "5000000"], - "profile": ["0", "1", "2"], - "preset-id": ["1", "2", "3"], - "control-rate": ["1", "2"], - "idrinterval": ["1", "256"], - "tuning-info-id": ["4", "2", "3"] - } -} +# Configure logging to show informational messages +logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') -videos = { - "base-daVinci": "./test.yuv" -} - -testsource = "videotestsrc pattern=smpte" - -videosrc = { - "raw":["filesrc location=", " ! rawvideoparse "], - "h264": ["filesrc location=", " ! decodebin"] - } - -psnr_check = { - "x264enc": "-pixel_format yuv420p -color_range pc", - "nvh264enc": "-pixel_format nv12 -color_range tv", - "nvv4l2h264enc": "-pixel_format nv12 -color_range tv" -} - -with_docker = [ "nvv4l2h264enc" ] - -repeats = 3 - -formats = { - "x264enc": "I420", - "nvh264enc": "NV12", - "nvv4l2h264enc": "NV12" -} - -profiles = ["baseline", "main"] - -videoconvert = { - "nvv4l2h264enc": "nvvideoconvert", - "nvh264enc": "videoconvert", - "x264enc": "videoconvert" -} - -video_info = { - "video1":"-video_size 1920x1080 -framerate 23.98", - "sample-surgery":"-video_size 1280x720 -framerate 29.97", - "base-daVinci": "-video_size 1280x720 -framerate 59.94" -} -gst_video_info = { - "video1":"format=I420,height=1080,width=1920,framerate=24000/1001", - "base-daVinci": "format=2 height=720 width=1280 colorimetry=bt601 framerate=60000/1001" -} - -latency_filename = "latency-traces-autotest.log" +config = None +def get_config(): + global config + if config is None: + config = AutotestConfig() + return config # Step-by-step: # 1. Generate all combinations for each encoder @@ -98,7 +36,7 @@ class Pipeline: self.pipeline = ( "GST_DEBUG_COLOR_MODE=off " + "GST_TRACERS=\"latency(flags=pipeline+element)\" " + - "GST_DEBUG=GST_TRACER:7 GST_DEBUG_FILE=" + latency_filename + " " + + "GST_DEBUG=GST_TRACER:7 GST_DEBUG_FILE=" + get_config().latency_filename + " " + self.pipeline ) return self @@ -112,8 +50,8 @@ class Pipeline: #self.pipeline += "tee name=t t. ! queue max-size-time=5000000000 max-size-bytes=100485760 max-size-buffers=1000 ! filesink location=\"base-autotest.yuv\" " def add_encoder(self, encoder, params): - self.pipeline += videoconvert[encoder] + " ! " - self.pipeline += "capsfilter caps=video/x-raw,format=" + formats[encoder] + " ! " + self.pipeline += get_config().videoconvert[encoder] + " ! " + self.pipeline += "capsfilter caps=video/x-raw,format=" + get_config().formats[encoder] + " ! " #self.__add_tee(encoder) self.options += " ".join(params) + " " #self.pipeline += "t. ! queue max-size-time=5000000000 max-size-bytes=100485760 max-size-buffers=1000 ! " @@ -132,11 +70,16 @@ class Pipeline: def makeVideoSrc(videoName): - return videosrc["raw"][0] + videos[videoName] + videosrc["raw"][1] + gst_video_info[videoName] + return ( + get_config().videosrc["raw"][0] + + get_config().videos[videoName] + + get_config().videosrc["raw"][1] + + get_config().gst_video_info[videoName] + ) def generateEncoderStrings(): - global options + options = get_config().options result = dict() for encoder, value in options.items(): result[encoder] = generate_combinations(value) @@ -169,7 +112,6 @@ def generate_combinations(config_dict): qualityDataframe = pd.DataFrame() latencyDataframe = pd.DataFrame() -dockerRunString = "sudo -S docker container exec deepstream-gst bash" def execPermissions(scriptFile = "to_exec.sh"): current_permissions = os.stat(scriptFile).st_mode @@ -184,10 +126,10 @@ def writeToExecFile(contents, file): def is_docker(func): def wrapper(pipeline): script_name = "to_exec.sh" - for encoder in with_docker: + for encoder in get_config().with_docker: if encoder in pipeline: writeToExecFile(pipeline, script_name) - pipeline = dockerRunString + f" {script_name}" + pipeline = get_config().docker_run_string + f" {script_name}" func(pipeline) return wrapper @@ -239,9 +181,9 @@ def run_autotest(): qualityDataframe = pd.DataFrame() latencyDataframe = pd.DataFrame() for params in combinations: - for profile in profiles: - for videoName, videoPath in videos.items(): - for _ in range(repeats): + for profile in get_config().profiles: + for videoName, videoPath in get_config().videos.items(): + for _ in range(get_config().repeats): filename = "autotest-" + encoder + "-" + profile + "-test-" + videoName + ".mp4" pipeline = Pipeline() pipeline = ( @@ -260,11 +202,11 @@ def run_autotest(): psnr_metrics, ssim_metrics = qa.run_quality_check( videoPath, filename, - video_info[videoName] + " " + psnr_check[encoder] + get_config().video_info[videoName] + " " + get_config().psnr_check[encoder] ) dfPsnr = qa.parse_quality_report(psnr_metrics, ssim_metrics) print("-----") - dfLatency = getLatencyTable(latency_filename) + dfLatency = getLatencyTable(get_config().latency_filename) columnsQ = pd.MultiIndex.from_tuples( [(encoder, profile, videoName, params, col) for col in dfPsnr.columns] ) diff --git a/requirements.txt b/requirements.txt index 1ec751e..0b770d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,5 +10,6 @@ pillow==11.3.0 pyparsing==3.2.5 python-dateutil==2.9.0.post0 pytz==2025.2 +PyYAML==6.0.3 six==1.17.0 tzdata==2025.2