Skip to content
......@@ -31,6 +31,7 @@
"""
from pathlib import Path
import platform
from tests.renderer.constants import (
BIN_SUFFIX_MERGETARGET,
......@@ -41,9 +42,17 @@ from tests.renderer.constants import (
METADATA_SCENES_TO_TEST,
)
if platform.system() == "Windows":
EXE_SUFFIX = ".exe"
elif platform.system() in ["Linux", "Darwin"]:
EXE_SUFFIX = ""
else:
assert False, f"Unsupported platform {platform.system()}"
""" Set up paths """
TESTS_DIR = Path(__file__).parent
RENDER_CFG_DIR = TESTS_DIR.joinpath("renderer_configs").resolve()
RENDER_FRAMING_CFG_DIR = TESTS_DIR.joinpath("renderer_configs").joinpath("framing").resolve()
ERROR_PATTERNS_DIR = TESTS_DIR.joinpath("error_patterns").resolve()
OUTPUT_PATH_REF = TESTS_DIR.joinpath("ref")
......@@ -69,6 +78,10 @@ RENDERER_CONFIGS_FASTCONV_RENDERER = [
str(cfg.stem) for cfg in RENDER_CFG_DIR.glob("*_fastconv.txt")
]
RENDERER_CONFIGS_FRAMING = [
str(cfg.stem) for cfg in RENDER_FRAMING_CFG_DIR.glob("framing*.txt")
]
RENDERER_CONFIGS_TO_TEST_AMBI = (
RENDERER_CONFIGS_DEFAULT_CODEC + RENDERER_CONFIGS_LC3PLUS_CODEC
)
......@@ -81,10 +94,13 @@ RENDERER_CONFIGS_TO_TEST_ISM = (
RENDERER_CONFIGS_TO_TEST_MASA = (
RENDERER_CONFIGS_DEFAULT_CODEC + RENDERER_CONFIGS_LC3PLUS_CODEC
)
RENDERER_CONFIGS_TO_TEST_OMASA = (
RENDERER_CONFIGS_DEFAULT_CODEC + RENDERER_CONFIGS_LC3PLUS_CODEC
)
RENDERER_CONFIGS_TO_TEST_OSBA = (
RENDERER_CONFIGS_DEFAULT_CODEC + RENDERER_CONFIGS_LC3PLUS_CODEC
)
RENDERER_CONFIGS_TO_TEST_PLC = RENDERER_CONFIGS_FASTCONV_RENDERER
RENDERER_CONFIGS_TO_TEST_PLC = RENDERER_CONFIGS_FASTCONV_RENDERER + RENDERER_CONFIGS_LC3PLUS_CODEC
""" Trajectories """
SPLIT_REND_HR_TRAJECTORIES_TO_TEST = [
......@@ -109,6 +125,14 @@ FORMAT_TO_IVAS_COD_FORMAT = {
"HOA3": ["-sba", "3"],
"MASA1": ["-masa", "1"],
"MASA2": ["-masa", "2"],
"OMASA_1_1": ["-ism_masa", "1", "1"],
"OMASA_1_2": ["-ism_masa", "2", "1"],
"OMASA_1_3": ["-ism_masa", "3", "1"],
"OMASA_1_4": ["-ism_masa", "4", "1"],
"OMASA_2_1": ["-ism_masa", "1", "2"],
"OMASA_2_2": ["-ism_masa", "2", "2"],
"OMASA_2_3": ["-ism_masa", "3", "2"],
"OMASA_2_4": ["-ism_masa", "4", "2"],
"OSBA_1_1": ["-ism_sba", "1", "1"],
"OSBA_1_2": ["-ism_sba", "1", "2"],
"OSBA_1_3": ["-ism_sba", "1", "3"],
......@@ -127,6 +151,7 @@ INPUT_FORMATS_AMBI_SPLIT_REND = ["FOA", "HOA3"]
INPUT_FORMATS_MC_SPLIT_REND = ["5_1", "7_1_4"]
INPUT_FORMATS_ISM_SPLIT_REND = ["ISM4"]
INPUT_FORMATS_MASA_SPLIT_REND = ["MASA1", "MASA2"]
INPUT_FORMATS_OMASA_SPLIT_REND = ["OMASA_1_1", "OMASA_2_4"] # number of TCs in MASA, number of ISM objects
INPUT_FORMATS_OSBA_SPLIT_REND = [
"OSBA_1_1",
"OSBA_4_3",
......@@ -136,6 +161,7 @@ IVAS_BITRATES_AMBI = ["80000", "512000"]
IVAS_BITRATES_MC = ["128000", "160000", "384000"]
IVAS_BITRATES_ISM = ["128000"]
IVAS_BITRATES_MASA = ["24400", "128000"]
IVAS_BITRATES_OMASA = ["16400", "32000", "96000", "384000"] # test all underlying coding modes (here, for 4 ISM)
IVAS_BITRATES_OSBA = ["256000", "512000"]
IVAS_MAX_ISM_BITRATE = {
......@@ -146,6 +172,8 @@ IVAS_MAX_ISM_BITRATE = {
}
RENDERER_FORMATS = ["BINAURAL_SPLIT_CODED", "BINAURAL_SPLIT_PCM"]
SPLIT_RENDERER_PRE_FRAMINGS = ["5", "10", "20"]
SPLIT_RENDERER_POST_FRAMINGS = ["5", "10", "20"]
INPUT_DURATION_SEC = 5
......@@ -168,10 +196,12 @@ SPLIT_PRE_DEC_CMD = [
"", # 2 -> pre-trajectory file
"-render_config",
"", # 4 -> render config file
"", # 5 -> renderer format
"-fr",
"", # 6 -> pre_rend_fs
"", # 7 -> renderer format
"48",
"", # 7 -> encoder bitstream
"", # 8 -> split rendering bitstream
"", # 9 -> encoder bitstream
"", # 10 -> split rendering bitstream
]
""" Split-pre Renderer commandline template """
......@@ -191,11 +221,13 @@ SPLIT_PRE_REND_CMD = [
"", # 12 -> renderer format
"-T",
"", # 14 -> post-trajectory file
"-fr",
"", # 16 -> pre rend framing
]
""" Split-post Renderer commandline template """
SPLIT_POST_REND_CMD = [
str(TESTS_DIR.parent.parent.joinpath("IVAS_rend")),
str(TESTS_DIR.parent.parent.joinpath("ISAR_post_rend")),
"-fs",
"48",
"-i",
......@@ -204,8 +236,8 @@ SPLIT_POST_REND_CMD = [
"", # 6 -> renderer format
"-o",
"", # 8 -> output file
"-of",
"BINAURAL",
"-T",
"", # 12 -> post-trajectory file
"", # 10 -> post-trajectory file
"-fr",
"", # 12 -> frame size
]
[SPLITREND]
BITRATE = 256000;
DOF = 0;
HQMODE = 0;
FRAMESIZE = 10;
CODEC = LC3PLUS;
[SPLITREND]
BITRATE = 256000;
DOF = 0;
HQMODE = 0;
FRAMESIZE = 5;
CODEC = LC3PLUS;
[SPLITREND]
BITRATE = 384000;
DOF = 1;
HQMODE = 0;
FRAMESIZE = 10;
CODEC = LC3PLUS;
[SPLITREND]
BITRATE = 384000;
DOF = 1;
HQMODE = 0;
FRAMESIZE = 5;
CODEC = LC3PLUS;
[SPLITREND]
BITRATE = 256000;
DOF = 0;
HQMODE = 0;
FRAMESIZE = 10;
CODEC = LCLD;
[SPLITREND]
BITRATE = 256000;
DOF = 0;
HQMODE = 0;
FRAMESIZE = 20;
CODEC = LCLD;
[SPLITREND]
BITRATE = 256000;
DOF = 0;
HQMODE = 0;
FRAMESIZE = 5;
CODEC = LCLD;
[SPLITREND]
BITRATE = 384000;
DOF = 1;
HQMODE = 0;
FRAMESIZE = 20;
CODEC = LCLD;
......@@ -35,40 +35,10 @@ import pytest
from tests.split_rendering.utils import *
def check_xfail(test_info, in_fmt, render_config, bitrate=None):
if (
"768k" in render_config
and "0dof" in render_config
and (
"lc3plus" in render_config
or (
in_fmt in INPUT_FORMATS_ISM_SPLIT_REND
or in_fmt in INPUT_FORMATS_MC_SPLIT_REND
)
or (
"external_split" in test_info.node.name
and in_fmt in INPUT_FORMATS_AMBI_SPLIT_REND
) # CREND for external renderer ambisonics rendering uses LC3plus by default
)
):
pytest.xfail("0DOF 768kbps LC3plus codec is unsupported")
if (
"256k" in render_config or "320k" in render_config
) and "0dof" not in render_config:
pytest.xfail("320kbps and lower are only supported with 0DOF")
if (
bitrate
and (in_fmt in INPUT_FORMATS_ISM_SPLIT_REND)
and (int(bitrate) > int(IVAS_MAX_ISM_BITRATE[in_fmt[-1]]))
):
pytest.skip(f"Unsupported configuration with {in_fmt} at {bitrate}bps")
""" Ambisonics """
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_AMBI)
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_AMBI)
......@@ -76,8 +46,6 @@ def check_xfail(test_info, in_fmt, render_config, bitrate=None):
def test_ambisonics_full_chain_split(
test_info, in_fmt, bitrate, render_config, trajectory
):
check_xfail(test_info, in_fmt, render_config, bitrate)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -86,17 +54,17 @@ def test_ambisonics_full_chain_split(
in_fmt=in_fmt,
bitrate=bitrate,
render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"),
binary_suffix=EXE_SUFFIX,
pre_trajectory=pre_trajectory,
post_trajectory=post_trajectory,
)
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_AMBI)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI_SPLIT_REND)
def test_ambisonics_external_split(test_info, in_fmt, render_config, trajectory):
check_xfail(test_info, in_fmt, render_config)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -112,6 +80,7 @@ def test_ambisonics_external_split(test_info, in_fmt, render_config, trajectory)
""" Multichannel """
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_MC)
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_MC)
......@@ -119,8 +88,6 @@ def test_ambisonics_external_split(test_info, in_fmt, render_config, trajectory)
def test_multichannel_full_chain_split(
test_info, in_fmt, bitrate, render_config, trajectory
):
check_xfail(test_info, in_fmt, render_config, bitrate)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -129,17 +96,17 @@ def test_multichannel_full_chain_split(
in_fmt=in_fmt,
bitrate=bitrate,
render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"),
binary_suffix=EXE_SUFFIX,
pre_trajectory=pre_trajectory,
post_trajectory=post_trajectory,
)
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_MC)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MC_SPLIT_REND)
def test_multichannel_external_split(test_info, in_fmt, render_config, trajectory):
check_xfail(test_info, in_fmt, render_config)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -155,13 +122,12 @@ def test_multichannel_external_split(test_info, in_fmt, render_config, trajector
""" ISM """
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_ISM)
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_ISM)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_ISM_SPLIT_REND)
def test_ism_full_chain_split(test_info, in_fmt, bitrate, render_config, trajectory):
check_xfail(test_info, in_fmt, render_config, bitrate)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -170,17 +136,17 @@ def test_ism_full_chain_split(test_info, in_fmt, bitrate, render_config, traject
in_fmt=in_fmt,
bitrate=bitrate,
render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"),
binary_suffix=EXE_SUFFIX,
pre_trajectory=pre_trajectory,
post_trajectory=post_trajectory,
)
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_ISM)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_ISM_SPLIT_REND)
def test_ism_external_split(test_info, in_fmt, render_config, trajectory):
check_xfail(test_info, in_fmt, render_config)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -196,13 +162,12 @@ def test_ism_external_split(test_info, in_fmt, render_config, trajectory):
""" MASA """
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_MASA)
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_MASA)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MASA_SPLIT_REND)
def test_masa_full_chain_split(test_info, in_fmt, bitrate, render_config, trajectory):
check_xfail(test_info, in_fmt, render_config, bitrate)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -211,17 +176,17 @@ def test_masa_full_chain_split(test_info, in_fmt, bitrate, render_config, trajec
in_fmt=in_fmt,
bitrate=bitrate,
render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"),
binary_suffix=EXE_SUFFIX,
pre_trajectory=pre_trajectory,
post_trajectory=post_trajectory,
)
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_MASA)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_MASA_SPLIT_REND)
def test_masa_external_split(test_info, in_fmt, render_config, trajectory):
check_xfail(test_info, in_fmt, render_config)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -234,16 +199,38 @@ def test_masa_external_split(test_info, in_fmt, render_config, trajectory):
)
""" OMASA """
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_OMASA)
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_OMASA)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_OMASA_SPLIT_REND)
def test_omasa_full_chain_split(test_info, in_fmt, bitrate, render_config, trajectory):
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
run_full_chain_split_rendering(
test_info,
in_fmt=in_fmt,
bitrate=bitrate,
render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"),
binary_suffix=EXE_SUFFIX,
pre_trajectory=pre_trajectory,
post_trajectory=post_trajectory,
)
""" OSBA """
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_OSBA)
@pytest.mark.parametrize("bitrate", IVAS_BITRATES_OSBA)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_OSBA_SPLIT_REND)
def test_osba_full_chain_split(test_info, in_fmt, bitrate, render_config, trajectory):
check_xfail(test_info, in_fmt, render_config, bitrate)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -252,6 +239,7 @@ def test_osba_full_chain_split(test_info, in_fmt, bitrate, render_config, trajec
in_fmt=in_fmt,
bitrate=bitrate,
render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"),
binary_suffix=EXE_SUFFIX,
pre_trajectory=pre_trajectory,
post_trajectory=post_trajectory,
)
......@@ -260,13 +248,12 @@ def test_osba_full_chain_split(test_info, in_fmt, bitrate, render_config, trajec
""" PLC """
@pytest.mark.create_ref
@pytest.mark.parametrize("error_pattern", PLC_ERROR_PATTERNS)
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_TO_TEST_PLC)
@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI_SPLIT_REND[-1:])
def test_post_rend_plc(test_info, in_fmt, render_config, trajectory, error_pattern):
check_xfail(test_info, in_fmt, render_config)
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -288,13 +275,13 @@ full_chain_split_pcm_params = [
("7_1_4", "512000", "split_renderer_config_3dofhq_512k_lc3plus"),
("ISM4", "384000", "split_renderer_config_2dof_768k_default"),
("MASA2", "256000", "split_renderer_config_3dof_384k_lcld"),
("OMASA_2_4", "256000", "split_renderer_config_3dof_384k_lcld"),
]
@pytest.mark.create_ref
@pytest.mark.parametrize("in_fmt,bitrate,render_config", full_chain_split_pcm_params)
def test_full_chain_split_pcm(test_info, in_fmt, bitrate, render_config):
check_xfail(test_info, in_fmt, render_config, bitrate)
trajectory = SPLIT_REND_HR_TRAJECTORIES_TO_TEST[0]
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -304,6 +291,7 @@ def test_full_chain_split_pcm(test_info, in_fmt, bitrate, render_config):
in_fmt=in_fmt,
bitrate=bitrate,
render_config=RENDER_CFG_DIR.joinpath(f"{render_config}.txt"),
binary_suffix=EXE_SUFFIX,
pre_trajectory=pre_trajectory,
post_trajectory=post_trajectory,
renderer_fmt="BINAURAL_SPLIT_PCM",
......@@ -317,10 +305,9 @@ external_split_pcm_params = [
]
@pytest.mark.create_ref
@pytest.mark.parametrize("in_fmt,render_config", external_split_pcm_params)
def test_external_split_pcm(test_info, in_fmt, render_config):
check_xfail(test_info, in_fmt, render_config)
trajectory = SPLIT_REND_HR_TRAJECTORIES_TO_TEST[0]
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
......@@ -333,3 +320,46 @@ def test_external_split_pcm(test_info, in_fmt, render_config):
post_trajectory=post_trajectory,
renderer_fmt="BINAURAL_SPLIT_PCM",
)
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_FRAMING)
@pytest.mark.parametrize("in_fmt", ["5_1"])
@pytest.mark.parametrize("pre_rend_fr", SPLIT_RENDERER_PRE_FRAMINGS)
@pytest.mark.parametrize("post_rend_fr", SPLIT_RENDERER_POST_FRAMINGS)
def test_framing_combinations_external_split(test_info, in_fmt, render_config, trajectory, post_rend_fr, pre_rend_fr):
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
run_external_split_rendering(
test_info,
in_fmt=in_fmt,
render_config=RENDER_FRAMING_CFG_DIR.joinpath(f"{render_config}.txt"),
pre_trajectory=pre_trajectory,
post_trajectory=post_trajectory,
post_rend_fr=post_rend_fr,
pre_rend_fr=pre_rend_fr,
)
@pytest.mark.create_ref
@pytest.mark.parametrize("trajectory", SPLIT_REND_HR_TRAJECTORIES_TO_TEST)
@pytest.mark.parametrize("render_config", RENDERER_CONFIGS_FRAMING)
@pytest.mark.parametrize("in_fmt", ["5_1"])
@pytest.mark.parametrize("pre_rend_fr", SPLIT_RENDERER_PRE_FRAMINGS)
@pytest.mark.parametrize("post_rend_fr", SPLIT_RENDERER_POST_FRAMINGS)
def test_framing_combinations_full_chain_split(
test_info, in_fmt, render_config, trajectory, post_rend_fr, pre_rend_fr
):
post_trajectory = HR_TRAJECTORY_DIR.joinpath(f"{trajectory}.csv")
pre_trajectory = post_trajectory.with_stem(f"{post_trajectory.stem}_delayed")
run_full_chain_split_rendering(
test_info,
in_fmt=in_fmt,
render_config=RENDER_FRAMING_CFG_DIR.joinpath(f"{render_config}.txt"),
pre_trajectory=pre_trajectory,
bitrate="256000",
post_trajectory=post_trajectory,
binary_suffix=EXE_SUFFIX,
post_rend_fr=post_rend_fr,
pre_rend_fr=pre_rend_fr,
)
......@@ -31,6 +31,7 @@
"""
import sys
import re
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Tuple
......@@ -38,13 +39,97 @@ from typing import Tuple
import numpy as np
import pytest
from tests.renderer.utils import check_BE, run_cmd, test_info
from tests.renderer.utils import check_BE, run_cmd, test_info, run_ivas_isar_enc_cmd, run_ivas_isar_dec_cmd, run_isar_post_rend_cmd, run_isar_ext_rend_cmd
from tests.split_rendering.constants import *
sys.path.append(SCRIPTS_DIR)
from pyaudio3dtools.audiofile import readfile, writefile
def lc3plus_used(test_info, in_fmt, render_config):
return (
# LC3plus used explicitly
"lc3plus" in render_config
# or default codec resolving to LC3plus in decoder
or (
"default" in render_config
and "full_chain" in test_info.node.name
and in_fmt in [*INPUT_FORMATS_ISM_SPLIT_REND, *INPUT_FORMATS_MC_SPLIT_REND]
)
# or default codec resolving to LC3plus in IVAS_rend
or ("default" in render_config and "external_split" in test_info.node.name)
)
FRAME_SIZE_RE = re.compile(r"(\d+)ms")
def transport_codec_frame_size_ms(test_info, in_fmt, render_config, pre_rend_fr):
explicit_frame_size_ms = FRAME_SIZE_RE.search(render_config)
# If explicit frame size set in config file, return that
if explicit_frame_size_ms:
return int(explicit_frame_size_ms[1])
# Otherwise infer default ISAR frame size.
if lc3plus_used(test_info, in_fmt, render_config):
# LC3plus always uses 5 ms
return 5
# LCLD adjusts to prerenderer frame size
return int(pre_rend_fr)
def check_xfail(
test_info, in_fmt, render_config, pre_rend_fr, post_rend_fr, ivas_bitrate=None
):
pre_rend_fr = int(pre_rend_fr)
post_rend_fr = int(post_rend_fr)
lc3plus_in_use = lc3plus_used(test_info, in_fmt, render_config)
if (
"256k" in render_config or "320k" in render_config
) and "0dof" not in render_config:
pytest.xfail("320kbps and lower are only supported with 0DOF")
if (
ivas_bitrate
and (in_fmt in INPUT_FORMATS_ISM_SPLIT_REND)
and (int(ivas_bitrate) > int(IVAS_MAX_ISM_BITRATE[in_fmt[-1]]))
):
pytest.skip(
f"Unsupported configuration with {in_fmt} at IVAS bitrate {ivas_bitrate}bps"
)
if not "0dof" in render_config and pre_rend_fr != 20:
pytest.xfail("pose correction (== !0dof) is expected to use 20ms")
if (
"1dof" in render_config or "2dof" in render_config or "3dof" in render_config
) and pre_rend_fr != 20:
pytest.xfail(
"unsupported framing: for 1+dof pre_rend_fr framing shall always be 20ms"
)
if pre_rend_fr < post_rend_fr:
pytest.xfail(
# This would require decoding multiple ISAR frames for one post renderer output frame, which is not supported.
"unsupported framing: Post-renderer frame size must be equal or smaller than ISAR codec frame size"
)
transport_codec_frame_size = transport_codec_frame_size_ms(
test_info, in_fmt, render_config, pre_rend_fr
)
if pre_rend_fr < transport_codec_frame_size:
pytest.xfail(
"unsupported framing: ISAR codec frame must fit in one output frame"
)
if not lc3plus_in_use and transport_codec_frame_size != pre_rend_fr:
pytest.xfail(
"unsupported framing: LCLD codec doesn't support aggregation. Pre-renderer (ISAR) frame size must match LCLD frame size."
)
def truncate_signal(
in_file: Path,
out_file: Path,
......@@ -74,32 +159,45 @@ def run_full_chain_split_rendering(
post_trajectory: Path,
renderer_fmt: str = "BINAURAL_SPLIT_CODED",
binary_suffix: str = "",
post_rend_fr: str = "20",
pre_rend_fr: str = "20",
) -> str:
"""
Runs the full split rendering chain consisting of
the IVAS encoder, decoder and split renderer
"""
check_xfail(test_info, in_fmt, render_config.name, pre_rend_fr, post_rend_fr, bitrate)
with TemporaryDirectory() as tmp_dir:
tmp_dir = Path(tmp_dir)
cut_in_file = tmp_dir.joinpath("cut_input.wav")
ivas_bitstream = tmp_dir.joinpath("ivas.192")
split_bitstream = tmp_dir.joinpath("split.bit")
#ivas_bitstream = tmp_dir.joinpath("ivas.192")
ivas_bitstream_stem = f"{in_fmt}_{bitrate}bps_{renderer_fmt}_split_full_config_{render_config.stem}_prerfr_{pre_rend_fr}_postrfr_{post_rend_fr}_ivas.192"
#split_bitstream = tmp_dir.joinpath("split.bit")
split_bitstream_stem = f"{in_fmt}_{bitrate}bps_{renderer_fmt}_split_full_config_{render_config.stem}_prerfr_{pre_rend_fr}_postrfr_{post_rend_fr}_split.bit"
if renderer_fmt == "BINAURAL_SPLIT_PCM":
split_md_file = tmp_dir.joinpath("split_md.bin")
out_file_stem = f"{in_fmt}_{bitrate}bps_{renderer_fmt}_{pre_trajectory.stem}_split_full_{post_trajectory.stem}_config_{render_config.stem}.wav"
#split_md_file = tmp_dir.joinpath("split_md.bin")
split_md_file_stem = f"{in_fmt}_{bitrate}bps_{renderer_fmt}_split_full_config_{render_config.stem}_prerfr_{pre_rend_fr}_postrfr_{post_rend_fr}_split_md.bit"
out_file_stem = f"{in_fmt}_{bitrate}bps_{renderer_fmt}_split_full_config_{render_config.stem}_prerfr_{pre_rend_fr}_postrfr_{post_rend_fr}_.wav"
if test_info.config.option.create_ref:
output_path_base = OUTPUT_PATH_REF
else:
output_path_base = OUTPUT_PATH_CUT
ivas_bitstream = output_path_base.joinpath(ivas_bitstream_stem)
split_bitstream = output_path_base.joinpath(split_bitstream_stem)
out_file = output_path_base.joinpath(out_file_stem)
if renderer_fmt == "BINAURAL_SPLIT_PCM":
split_md_file = output_path_base.joinpath(split_md_file_stem)
# check for metadata files
if in_fmt.upper().startswith("OSBA"):
# use same MD as ISM
in_meta_files = FORMAT_TO_METADATA_FILES[f"ISM{in_fmt[5]}"]
elif in_fmt.upper().startswith("ISM") or in_fmt.upper().startswith("MASA"):
elif in_fmt.upper().startswith("ISM") or in_fmt.upper().startswith("MASA") or in_fmt.upper().startswith("OMASA"):
in_meta_files = FORMAT_TO_METADATA_FILES[in_fmt]
else:
in_meta_files = None
......@@ -126,7 +224,7 @@ def run_full_chain_split_rendering(
cmd[1:1] = FORMAT_TO_IVAS_COD_FORMAT[in_fmt]
run_cmd(cmd)
run_ivas_isar_enc_cmd(cmd)
# decode to split-rendering bitstream
cmd = SPLIT_PRE_DEC_CMD[:]
......@@ -136,30 +234,32 @@ def run_full_chain_split_rendering(
cmd[0] += binary_suffix
cmd[2] = str(pre_trajectory)
cmd[4] = str(render_config)
cmd[5] = renderer_fmt
cmd[7] = str(ivas_bitstream)
cmd[8] = str(split_bitstream)
cmd[6] = str(pre_rend_fr)
cmd[7] = renderer_fmt
cmd[9] = str(ivas_bitstream)
cmd[10] = str(split_bitstream)
if renderer_fmt == "BINAURAL_SPLIT_PCM":
cmd[5:5] = ["-om", str(split_md_file)]
run_cmd(cmd)
run_ivas_isar_dec_cmd(cmd)
# run split renderer
cmd = SPLIT_POST_REND_CMD[:]
if test_info.config.option.create_ref:
cmd[0] += BIN_SUFFIX_MERGETARGET
#if test_info.config.option.create_ref:
# cmd[0] += BIN_SUFFIX_MERGETARGET
cmd[0] += binary_suffix
cmd[4] = str(split_bitstream)
cmd[6] = renderer_fmt
cmd[8] = str(out_file)
cmd[12] = str(post_trajectory)
cmd[10] = str(post_trajectory)
cmd[12] = post_rend_fr
if renderer_fmt == "BINAURAL_SPLIT_PCM":
cmd[7:7] = ["-im", str(split_md_file)]
run_cmd(cmd)
run_isar_post_rend_cmd(cmd)
if test_info.config.option.create_cut:
# CUT creation mode will run a comparison with REF
......@@ -189,19 +289,23 @@ def run_external_split_rendering(
renderer_fmt: str = "BINAURAL_SPLIT_CODED",
binary_suffix: str = "",
is_comparetest: bool = False,
post_rend_fr: str = "20",
pre_rend_fr: str = "20",
) -> Tuple[np.ndarray, int]:
"""
Runs the exeternal split rendering chain consisting of
the IVAS renderer in split-pre and split-post rendering mode
"""
check_xfail(test_info, in_fmt, render_config.name, pre_rend_fr, post_rend_fr)
with TemporaryDirectory() as tmp_dir:
tmp_dir = Path(tmp_dir)
cut_in_file = tmp_dir.joinpath("cut_input.wav")
split_bitstream = tmp_dir.joinpath("split.bit")
if renderer_fmt == "BINAURAL_SPLIT_PCM":
split_md_file = tmp_dir.joinpath("split_md.bin")
out_file_stem = f"{in_fmt}_{renderer_fmt}_{pre_trajectory.stem}_split_ext_{post_trajectory.stem}_config_{render_config.stem}.wav"
out_file_stem = f"{in_fmt}_{renderer_fmt}_split_ext_config_{render_config.stem}_postrfr_{pre_rend_fr}_prerfr_{post_rend_fr}.wav"
if test_info.config.option.create_ref:
output_path_base = OUTPUT_PATH_REF
......@@ -239,6 +343,7 @@ def run_external_split_rendering(
cmd[10] = str(split_bitstream)
cmd[12] = renderer_fmt
cmd[14] = str(pre_trajectory)
cmd[16] = pre_rend_fr
if renderer_fmt == "BINAURAL_SPLIT_PCM":
cmd[13:13] = ["-om", str(split_md_file)]
......@@ -246,18 +351,19 @@ def run_external_split_rendering(
if in_meta_files:
cmd[9:9] = ["-im", *in_meta_files]
run_cmd(cmd)
run_isar_ext_rend_cmd(cmd)
# run split renderer
cmd = SPLIT_POST_REND_CMD[:]
if test_info.config.option.create_ref:
cmd[0] += BIN_SUFFIX_MERGETARGET
#if test_info.config.option.create_ref:
# cmd[0] += BIN_SUFFIX_MERGETARGET
cmd[0] += binary_suffix
cmd[4] = str(split_bitstream)
cmd[6] = renderer_fmt
cmd[8] = str(out_file)
cmd[12] = str(post_trajectory)
cmd[10] = str(post_trajectory)
cmd[12] = post_rend_fr
if renderer_fmt == "BINAURAL_SPLIT_PCM":
cmd[7:7] = ["-im", str(split_md_file)]
......@@ -265,7 +371,7 @@ def run_external_split_rendering(
if plc_error_pattern:
cmd[1:1] = ["-prbfi", str(plc_error_pattern)]
run_cmd(cmd)
run_isar_ext_rend_cmd(cmd)
if test_info.config.option.create_cut:
# CUT creation mode will run a comparison with REF
......