Skip to content

Commit

Permalink
Add: Integrity tests (#1032)
Browse files Browse the repository at this point in the history
Add integrity tests that compare source and output files for st20p and
st30p. In st20p the files are compared by frame checksums, in st30p the
files are compared by bytes.
  • Loading branch information
staszczuk authored Jan 21, 2025
1 parent c48cd2f commit 5e85a13
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 1 deletion.
6 changes: 5 additions & 1 deletion tests/validation/tests/Engine/RxTxApp.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ def add_st20p_sessions(
packing: str = "BPM",
enable_rtcp: bool = False,
measure_latency: bool = False,
out_url: str = "",
) -> dict:
config = add_interfaces(
config=config, nic_port_list=nic_port_list, test_mode=test_mode
Expand Down Expand Up @@ -224,6 +225,7 @@ def add_st20p_sessions(
config["rx_sessions"][0]["st20p"][0]["enable_rtcp"] = enable_rtcp
config["rx_sessions"][0]["st20p"][0]["measure_latency"] = measure_latency
config["tx_sessions"][0]["st20p"][0]["st20p_url"] = st20p_url
config["rx_sessions"][0]["st20p"][0]["st20p_url"] = out_url

return config

Expand Down Expand Up @@ -286,6 +288,7 @@ def add_st30p_sessions(
audio_channel: list = ["U02"],
audio_sampling: str = "96kHz",
audio_ptime: str = "1",
out_url: str = "",
) -> dict:
config = add_interfaces(
config=config, nic_port_list=nic_port_list, test_mode=test_mode
Expand All @@ -304,7 +307,8 @@ def add_st30p_sessions(
config["tx_sessions"][0]["st30p"][0]["audio_ptime"] = audio_ptime
config["rx_sessions"][0]["st30p"][0]["audio_ptime"] = audio_ptime
config["tx_sessions"][0]["st30p"][0]["audio_url"] = filename
config["rx_sessions"][0]["st30p"][0]["audio_url"] = filename
config["rx_sessions"][0]["st30p"][0]["audio_url"] = out_url

return config


Expand Down
156 changes: 156 additions & 0 deletions tests/validation/tests/Engine/integrity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2024-2025 Intel Corporation

import hashlib
import re
from math import floor

from tests.Engine.execute import log_fail


def check_st20p_integrity(src_url: str, out_url: str, frame_size: int):
src_chunk_sums = []

with open(src_url, "rb") as f:
while chunk := f.read(frame_size):
chunk_sum = hashlib.md5(chunk).hexdigest()
src_chunk_sums.append(chunk_sum)

out_chunk_sums = []

with open(out_url, "rb") as f:
while chunk := f.read(frame_size):
chunk_sum = hashlib.md5(chunk).hexdigest()
out_chunk_sums.append(chunk_sum)

if len(src_chunk_sums) < len(out_chunk_sums):
for i in range(len(src_chunk_sums)):
if src_chunk_sums[i] != out_chunk_sums[i]:
log_fail(f"Received frame {i} is invalid")
return False
else:
for i in range(len(out_chunk_sums)):
if out_chunk_sums[i] != src_chunk_sums[i]:
log_fail(f"Received frame {i} is invalid")
return False

return True


def calculate_yuv_frame_size(width: int, height: int, file_format: str):
match file_format:
case "YUV422RFC4175PG2BE10":
pixel_size = 2.5
case "YUV422PLANAR10LE":
pixel_size = 4
case _:
log_fail(f"Size of {file_format} pixel is not known")

return int(width * height * pixel_size)


def check_st30p_integrity(src_url: str, out_url: str, size: int):
src_chunks = []

with open(src_url, "rb") as f:
while chunk := f.read(size):
src_chunks.append(chunk)

out_chunks = []

with open(out_url, "rb") as f:
while chunk := f.read(size):
out_chunks.append(chunk)

if len(src_chunks) < len(out_chunks):
for i in range(len(src_chunks)):
if src_chunks[i] != out_chunks[i]:
log_fail(f"Received frame {i} is invalid")
return False
else:
for i in range(len(out_chunks)):
if out_chunks[i] != src_chunks[i]:
log_fail(f"Received frame {i} is invalid")
return False

return True


def calculate_st30p_framebuff_size(
format: str, ptime: str, sampling: str, channel: str
):
match format:
case "PCM8":
sample_size = 1
case "PCM16":
sample_size = 2
case "PCM24":
sample_size = 3

match sampling:
case "48kHz":
match ptime:
case "1":
sample_num = 48
case "0.12":
sample_num = 6
case "0.25":
sample_num = 12
case "0.33":
sample_num = 16
case "4":
sample_num = 192
case "96kHz":
match ptime:
case "1":
sample_num = 96
case "0.12":
sample_num = 12
case "0.25":
sample_num = 24
case "0.33":
sample_num = 32
case "4":
sample_num = 384

match channel:
case "M":
channel_num = 1
case "DM" | "ST" | "LtRt" | "AES3":
channel_num = 2
case "51":
channel_num = 6
case "71":
channel_num = 8
case "222":
channel_num = 24
case "SGRP":
channel_num = 4
case _:
match = re.match(r"^U(\d{2})$", channel)

if match:
channel_num = int(match.group(1))

packet_size = sample_size * sample_num * channel_num

match ptime:
case "1":
packet_time = 1_000_000 * 1
case "0.12":
packet_time = 1_000_000 * 0.125
case "0.25":
packet_time = 1_000_000 * 0.25
case "0.33":
packet_time = 1_000_000 * 1 / 3
case "4":
packet_time = 1_000_000 * 4

desired_frame_time = 10_000_000

packet_per_frame = 1

if desired_frame_time > packet_time:
packet_per_frame = floor(desired_frame_time / packet_time)

return packet_per_frame * packet_size
23 changes: 23 additions & 0 deletions tests/validation/tests/Engine/media_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,15 @@
"format": "YUV_422_10bit",
"width": 1280,
"height": 720,
"fps": 25,
},
Penguin_1080p={
"filename": "HDR_BBC_v4_008_Penguin1_1920x1080_10bit_25Hz_P422_180frames.yuv",
"file_format": "YUV422PLANAR10LE",
"format": "YUV_422_10bit",
"width": 1920,
"height": 1080,
"fps": 25,
},
)

Expand Down Expand Up @@ -355,96 +357,117 @@
)

yuv_files_422rfc10 = dict(
Penguin_720p={
"filename": "HDR_BBC_v4_008_Penguin1_1280x720_10bit_25Hz_P422_180frames.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 1280,
"height": 720,
"fps": 25,
},
Penguin_1080p={
"filename": "HDR_BBC_v4_008_Penguin1_1920x1080_10bit_25Hz_180frames_yuv422p10be_To_yuv422rfc4175be10.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 1920,
"height": 1080,
"fps": 25,
},
Penguin_4K={
"filename": "HDR_BBC_v4_008_Penguin1_3840x2160_10bit_25Hz_P422_180frames_yuv422rfc4175be10.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 3840,
"height": 2160,
"fps": 25,
},
Penguin_8K={
"filename": "HDR_BBC_v4_008_Penguin1_7680x4320_10bit_25Hz_P422_To_yuv422rfc4175be10_180frames.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 7680,
"height": 4320,
"fps": 25,
},
Crosswalk_720p={
"filename": "Netflix_Crosswalk_1280x720_10bit_60Hz_P422_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 1280,
"height": 720,
"fps": 60,
},
Crosswalk_1080p={
"filename": "Netflix_Crosswalk_1920x1080_10bit_60Hz_P422_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 1920,
"height": 1080,
"fps": 60,
},
Crosswalk_4K={
"filename": "Netflix_Crosswalk_3840x2160_10bit_60Hz_P422_To_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 3840,
"height": 2160,
"fps": 60,
},
ParkJoy_720p={
"filename": "ParkJoy_1280x720_10bit_50Hz_P422_To_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 1280,
"height": 720,
"fps": 50,
},
ParkJoy_1080p={
"filename": "ParkJoy_1920x1080_10bit_50Hz_P422_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 1920,
"height": 1080,
"fps": 50,
},
ParkJoy_4K={
"filename": "ParkJoy_3840x2160_10bit_50Hz_P422_To_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 3840,
"height": 2160,
"fps": 50,
},
Pedestrian_720p={
"filename": "Plalaedit_Pedestrian_10bit_1280x720_30Hz_P420_To_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 1280,
"height": 720,
"fps": 30,
},
Pedestrian_1080p={
"filename": "Plalaedit_Pedestrian_10bit_1920x1080_30Hz_P420_To_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 1920,
"height": 1080,
"fps": 30,
},
Pedestrian_4K={
"filename": "Plalaedit_Pedestrian_10bit_3840x2160_30Hz_P420_To_yuv422p10be_To_yuv422YCBCR10be.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 3840,
"height": 2160,
"fps": 30,
},
test_4K={
"filename": "test_3840x2160_for_25fps.yuv",
"file_format": "YUV422RFC4175PG2BE10",
"format": "YUV_422_10bit",
"width": 3840,
"height": 2160,
"fps": 25,
},
test_8K={
"filename": "test_8k.yuv",
Expand Down
1 change: 1 addition & 0 deletions tests/validation/tests/Engine/rxtxapp_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@
"measure_latency": False,
"display": False,
"enable_rtcp": False,
"st20p_url": "",
}

# st22p
Expand Down
Empty file.
55 changes: 55 additions & 0 deletions tests/validation/tests/single/st20p/integrity/test_integrity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2024-2025 Intel Corporation

import os

import pytest
import tests.Engine.RxTxApp as rxtxapp
from tests.Engine.execute import log_info
from tests.Engine.integrity import calculate_yuv_frame_size, check_st20p_integrity
from tests.Engine.logging import LOG_FOLDER
from tests.Engine.media_files import yuv_files_422p10le, yuv_files_422rfc10


@pytest.mark.parametrize(
"st20p_file, fps",
[
(yuv_files_422rfc10["Penguin_720p"], "p25"),
(yuv_files_422rfc10["Penguin_1080p"], "p25"),
(yuv_files_422p10le["Penguin_720p"], "p25"),
(yuv_files_422p10le["Penguin_1080p"], "p25"),
],
)
def test_integrity(build, media, nic_port_list, test_time, st20p_file, fps):
st20p_file_url = os.path.join(media, st20p_file["filename"])

out_file_url = os.path.join(os.getcwd(), LOG_FOLDER, "latest", "out.yuv")

config = rxtxapp.create_empty_config()
config = rxtxapp.add_st20p_sessions(
config=config,
nic_port_list=nic_port_list,
test_mode="unicast",
height=st20p_file["height"],
width=st20p_file["width"],
fps=fps,
input_format=st20p_file["file_format"],
transport_format=st20p_file["format"],
output_format=st20p_file["file_format"],
st20p_url=st20p_file_url,
out_url=out_file_url,
)

rxtxapp.execute_test(config=config, build=build, test_time=test_time)

frame_size = calculate_yuv_frame_size(
st20p_file["width"], st20p_file["height"], st20p_file["file_format"]
)
result = check_st20p_integrity(
src_url=st20p_file_url, out_url=out_file_url, frame_size=frame_size
)

if result:
log_info("INTEGRITY PASS")
else:
log_info("INTEGRITY FAIL")
Empty file.
Loading

0 comments on commit 5e85a13

Please sign in to comment.