diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a8ce2cb83060d32b4ebc0c6d9f7bb24e6d7169cb..6caca316df438cad8240abf2b94438f2b051f15c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,6 +20,11 @@ variables: - 'default' - 'test-be-release' - 'test-long-self-test' + - 'test-be-release-pre-test' + REF_COMMIT: + description: "Ref commit id or ref release tag. To be used by Manual pipeline 'test-be-release-pre-test'" + DUT_COMMIT: + description: "Dut commit id or dut release tag. To be used by Manual pipeline 'test-be-release-pre-test'" default: @@ -50,6 +55,9 @@ workflow: - if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'test-long-self-test' variables: IVAS_PIPELINE_NAME: 'Test long self-test against main pipeline: $CI_COMMIT_BRANCH' + - if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'test-be-release-pre-test' + variables: + IVAS_PIPELINE_NAME: 'Test BE to release pre-test pipeline: $REF_COMMIT vs $DUT_COMMIT' - if: $CI_PIPELINE_SOURCE == 'trigger' stages: @@ -180,6 +188,8 @@ stages: when: never - if: $MANUAL_PIPELINE_TYPE == 'test-long-self-test' # Skip all the normal jobs when testing manually against release codec when: never + - if: $MANUAL_PIPELINE_TYPE == 'test-be-release-pre-test' # Skip all the normal jobs when testing manually against release codec + when: never - when: on_success .rules-merge-request: @@ -1193,6 +1203,75 @@ test-be-to-release: - logs/ expose_as: "test-be-to-release results" +test-be-release-pre-test: + stage: test + tags: + - test-be-to-release-windows + resource_group: ivas-be-to-release-test-resource + timeout: "22 hours" # to be reviewed + rules: + - if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'test-be-release-pre-test' + script: + + - git checkout $REF_COMMIT + - echo "REF_COMMIT $REF_COMMIT" + - MSBuild.exe .\Workspace_msvc\Workspace_msvc.sln /property:Configuration=Debug /p:Platform=win32 /m + + - mv IVAS_cod.exe IVAS_cod_ref.exe + - mv IVAS_dec.exe IVAS_dec_ref.exe + - mv IVAS_rend.exe IVAS_rend_ref.exe + + - git checkout $DUT_COMMIT + - echo "DUT_COMMIT $DUT_COMMIT" + - MSBuild.exe .\Workspace_msvc\Workspace_msvc.sln /property:Configuration=Debug /p:Platform=win32 /m + + - mv IVAS_cod.exe IVAS_cod_dut.exe + - mv IVAS_dec.exe IVAS_dec_dut.exe + - mv IVAS_rend.exe IVAS_rend_dut.exe + + # checkout current branch with codec_be_to_accepted_release be-test + - git checkout $CI_COMMIT_SHORT_SHA + + - mkdir logs + + - mkdir tests\codec_be_to_accepted_release\ref + - mkdir tests\codec_be_to_accepted_release\dut + + # create references + - echo "generate references" + + # encoder, constant brate + - $testcase_timeout=240 # to be reviewed + - $zero_errors_enc_const_br_ref=0 + - $zero_failures_ref=0 + - ("& python -m pytest .\tests\codec_be_to_accepted_release\encoder\test_encoder_constant_bitrate.py --update_ref 1 --ref_encoder_path IVAS_cod_ref.exe --ref_decoder_path IVAS_dec_ref.exe --dut_encoder_path IVAS_cod_dut.exe --dut_decoder_path IVAS_dec_dut.exe --html=logs/report-enc-const_br-ref.html --self-contained-html --junit-xml=logs/report-junit-enc-const_br-ref.xml --testcase_timeout $testcase_timeout | out-null") | Invoke-Expression + - IF (!(Select-String logs/report-junit-enc-const_br-ref.xml -Pattern 'errors="0"')){$zero_errors_enc_const_br_ref=1; echo "Errors encountered in ref generation"} + - IF (!(Select-String logs/report-junit-enc-const_br-ref.xml -Pattern 'failures="0"')){$zero_failures_ref=1; echo "Failed tests encountered in ref generation"} + + # test encoder dut + - echo "dut test encoder" + + - $zero_errors_enc_const_br_dut=0 + - $zero_failures_dut=0 + - ("& python -m pytest .\tests\codec_be_to_accepted_release\encoder\test_encoder_constant_bitrate.py --ref_encoder_path IVAS_cod_ref.exe --ref_decoder_path IVAS_dec_ref.exe --dut_encoder_path IVAS_cod_dut.exe --dut_decoder_path IVAS_dec_dut.exe --html=logs/report-enc-const_br-dut.html --self-contained-html --junit-xml=logs/report-junit-enc-const_br-dut.xml --testcase_timeout $testcase_timeout | out-null") | Invoke-Expression + - IF (!(Select-String logs/report-junit-enc-const_br-dut.xml -Pattern 'errors="0"')){$zero_errors_enc_const_br_dut=1; echo "Errors encountered in dut"} + - IF (!(Select-String logs/report-junit-enc-const_br-dut.xml -Pattern 'failures="0"')){$zero_failures_dut=1; echo "Failed tests encountered in dut"} + + - IF($zero_errors_enc_const_br_ref -ne 0 -or $zero_errors_enc_const_br_dut -ne 0 ) {echo "Errors encountered"; exit $EXIT_CODE_FAIL} + - IF($zero_failures_ref -ne 0 ) {echo "Failed tests encountered in ref generation"; exit $EXIT_CODE_FAIL} + - IF($zero_failures_dut -ne 0 ) {echo "Non-bitexact cases encountered!"; exit $EXIT_CODE_NON_BE} + + artifacts: + name: "test-be-to-release--$REF_COMMIT-to-$DUT_COMMIT--results" + when: always + expire_in: 1 week + paths: + - logs/ + expose_as: "test-be-to-release results" + reports: + junit: + - logs/report-junit*.xml + test-long-self-test: tags: diff --git a/tests/codec_be_to_accepted_release/__init__.py b/tests/codec_be_to_accepted_release/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e01382cefb1c52e6d6e9826a8b891e2b6545ebf9 --- /dev/null +++ b/tests/codec_be_to_accepted_release/__init__.py @@ -0,0 +1,92 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import filecmp +import subprocess +from itertools import product +from ..testconfig import MD5_REF_DICT +from .constants import ( + TESTVECTOR_FOR_INPUT_FORMAT, + TESTV_PATH, + REF_PATH, + SAMPLING_RATES_ALL, + MAX_BAND_ALL, +) + + +def is_be_to_ref(dut_file): + """ + Check bitexactness either by comparing files directly or by comparing MD5 sums + """ + if MD5_REF_DICT == dict(): + ref_file = REF_PATH.joinpath(dut_file.name) + is_be = filecmp.cmp(dut_file, ref_file) + else: + md5_ref = MD5_REF_DICT[dut_file.name] + cmd = f"powershell.exe (Get-FileHash {str(dut_file)} -Algorithm MD5).Hash" + md5_dut = subprocess.check_output(cmd, shell=True).decode().splitlines()[-1] + is_be = md5_ref == md5_dut + + return is_be + + +def get_bitstream_path( + base_path, + testv_name, + encoder_format, + bitrate, + sampling_rate, + max_band, + dtx, + suffix="", +): + bs_name = f"{testv_name}-{encoder_format}-{bitrate}kbps-{sampling_rate}kHz-max_band_{max_band}-{dtx}{suffix}.192" + return base_path.joinpath(bs_name) + + +def get_testv_path(input_format, sampling_rate): + testv = TESTVECTOR_FOR_INPUT_FORMAT[input_format].format(fs=sampling_rate) + return TESTV_PATH.joinpath(testv) + + +def get_valid_fs_max_band_pairs(add_narrow_band: bool = False): + """ + Get all sensible sampling rate and max_band value combinations, i.e. pair each sampling rate + with all bw options which indicate the same or lower bandwidth (codec will "crop" if bw + given is higher than sampling rate). + + add_narrow_band: include NB in max_band values, this only applies for stereo_dmx_evs + """ + fs, mb = SAMPLING_RATES_ALL, list(MAX_BAND_ALL) + if add_narrow_band: + mb.insert(0, "NB") + + params = [(r, b) for r, b in product(fs, mb) if fs.index(r) >= mb.index(b)] + return params diff --git a/tests/codec_be_to_accepted_release/constants.py b/tests/codec_be_to_accepted_release/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..0f836040b7b659319823a9fa3a77f9b5accf6323 --- /dev/null +++ b/tests/codec_be_to_accepted_release/constants.py @@ -0,0 +1,539 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +from itertools import product +from pathlib import Path +import os + +HERE = Path(__file__).parent +TESTV_PATH = Path(os.environ.get("BE_TESTV_DIR", HERE.joinpath("testv"))) +REF_PATH = Path(os.environ.get("BE_REF_DIR", HERE.joinpath("ref"))) +DUT_PATH = HERE.joinpath("dut") + + +def collapse_into_list_of_pairs(params): + return [p[0] + p[1:] for p in params] + + +def bitrates_between(lowest, highest): + """ + Helper function to reduce slicing errors due to mistakes and later changes + """ + return [b for b in BITRATES_ALL if b >= lowest and b <= highest] + + +def get_file_from_repo(path): + """ + Helper for getting a file from the repo, e.g. from scripts/testv. The path needs to be given relative to the repository root! + """ + repo_root = HERE.joinpath("../..").resolve().absolute() + return str(repo_root.joinpath(path)) + + +DTX_ON = "DTXon" +DTX_OFF = "DTXoff" + +ISM_MD_BASIC = "MDbasic" +ISM_MD_EXTENDED = "MDextended" +ISM_MD_NULL = "MDnull" + +SBA_FOA_PCA_ON = "PCAon" +SBA_FOA_PCA_OFF = "PCAoff" + +TESTVECTOR_FOR_INPUT_FORMAT = { + "STEREO": "ltv{fs}_STEREO.wav", + "MC_5_1": "ltv{fs}_MC51.wav", + "MC_5_1_2": "ltv{fs}_MC512.wav", + "MC_5_1_4": "ltv{fs}_MC514.wav", + "MC_7_1": "ltv{fs}_MC71.wav", + "MC_7_1_4": "ltv{fs}_MC714.wav", + "FOA": "ltv{fs}_FOA.wav", + "HOA2": "ltv{fs}_HOA2.wav", + "HOA3": "ltv{fs}_HOA3.wav", + "PlanarFOA": "ltv{fs}_FOA.wav", + "PlanarHOA2": "ltv{fs}_HOA2.wav", + "PlanarHOA3": "ltv{fs}_HOA3.wav", + "ISM1": "ltv{fs}_1ISM.wav", + "ISM2": "ltv{fs}_2ISM.wav", + "ISM3": "ltv{fs}_3ISM.wav", + "ISM4": "ltv{fs}_4ISM.wav", + "ISM1": "ltv{fs}_1ISM.wav", + "ISM2": "ltv{fs}_2ISM.wav", + "ISM3": "ltv{fs}_3ISM.wav", + "ISM4": "ltv{fs}_4ISM.wav", + "MASA_1TC_1DIR": "ltv{fs}_MASA1TC.wav", + "MASA_2TC_1DIR": "ltv{fs}_MASA2TC.wav", + "MASA_1TC_2DIR": "ltv{fs}_MASA1TC.wav", + "MASA_2TC_2DIR": "ltv{fs}_MASA2TC.wav", + "OMASA_ISM1_MASA_1TC_1DIR": "ltv{fs}_OMASA_1ISM_1TC.wav", # to be reviewed + "OMASA_ISM1_MASA_1TC_2DIR": "ltv{fs}_OMASA_1ISM_1TC.wav", + "OMASA_ISM1_MASA_2TC_1DIR": "ltv{fs}_OMASA_1ISM_2TC.wav", + "OMASA_ISM1_MASA_2TC_2DIR": "ltv{fs}_OMASA_1ISM_2TC.wav", + "OMASA_ISM2_MASA_1TC_1DIR": "ltv{fs}_OMASA_2ISM_1TC.wav", + "OMASA_ISM2_MASA_1TC_2DIR": "ltv{fs}_OMASA_2ISM_1TC.wav", + "OMASA_ISM2_MASA_2TC_1DIR": "ltv{fs}_OMASA_2ISM_2TC.wav", + "OMASA_ISM2_MASA_2TC_2DIR": "ltv{fs}_OMASA_2ISM_2TC.wav", + "OMASA_ISM3_MASA_1TC_1DIR": "ltv{fs}_OMASA_3ISM_1TC.wav", + "OMASA_ISM3_MASA_1TC_2DIR": "ltv{fs}_OMASA_3ISM_1TC.wav", + "OMASA_ISM3_MASA_2TC_1DIR": "ltv{fs}_OMASA_3ISM_2TC.wav", + "OMASA_ISM3_MASA_2TC_2DIR": "ltv{fs}_OMASA_3ISM_2TC.wav", + "OMASA_ISM4_MASA_1TC_1DIR": "ltv{fs}_OMASA_4ISM_1TC.wav", + "OMASA_ISM4_MASA_1TC_2DIR": "ltv{fs}_OMASA_4ISM_1TC.wav", + "OMASA_ISM4_MASA_2TC_1DIR": "ltv{fs}_OMASA_4ISM_2TC.wav", + "OMASA_ISM4_MASA_2TC_2DIR": "ltv{fs}_OMASA_4ISM_2TC.wav", + "OSBA_ISM1_FOA": "ltv{fs}_OSBA_1ISM_FOA.wav", + "OSBA_ISM1_HOA2": "ltv{fs}_OSBA_1ISM_HOA2.wav", + "OSBA_ISM1_HOA3": "ltv{fs}_OSBA_1ISM_HOA3.wav", + "OSBA_ISM2_FOA": "ltv{fs}_OSBA_2ISM_FOA.wav", + "OSBA_ISM2_HOA2": "ltv{fs}_OSBA_2ISM_HOA2.wav", + "OSBA_ISM2_HOA3": "ltv{fs}_OSBA_2ISM_HOA3.wav", + "OSBA_ISM3_FOA": "ltv{fs}_OSBA_3ISM_FOA.wav", + "OSBA_ISM3_HOA2": "ltv{fs}_OSBA_3ISM_HOA2.wav", + "OSBA_ISM3_HOA3": "ltv{fs}_OSBA_3ISM_HOA3.wav", + "OSBA_ISM4_FOA": "ltv{fs}_OSBA_4ISM_FOA.wav", + "OSBA_ISM4_HOA2": "ltv{fs}_OSBA_4ISM_HOA2.wav", + "OSBA_ISM4_HOA3": "ltv{fs}_OSBA_4ISM_HOA3.wav", +} +METADATA_FOR_INPUT_FORMAT = { + "ISM1": ["ltvISM1.csv"], + "ISM2": ["ltvISM1.csv", "ltvISM2.csv"], + "ISM3": ["ltvISM1.csv", "ltvISM2.csv", "ltvISM3.csv"], + "ISM4": ["ltvISM1.csv", "ltvISM2.csv", "ltvISM3.csv", "ltvISM4.csv"], + "MASA_1TC_1DIR": ["ltv48_OMASA_1ISM_1TC.met"], # to be reviewed + "MASA_2TC_1DIR": ["ltv48_MASA2TC.met"], + "MASA_1TC_2DIR": ["ltv48_OMASA_2ISM_1TC.met"], + "MASA_2TC_2DIR": ["ltv48_MASA2TC.met"], +} +CMDL_OPTIONS_FOR_INPUT_FORMAT = { + "STEREO": ["-stereo"], + "MC_5_1": ["-mc", "5_1"], + "MC_5_1_2": ["-mc", "5_1_2"], + "MC_5_1_4": ["-mc", "5_1_4"], + "MC_7_1": ["-mc", "7_1"], + "MC_7_1_4": ["-mc", "7_1_4"], + "FOA": ["-sba", "+1"], + "HOA2": ["-sba", "+2"], + "HOA3": ["-sba", "+3"], + "PlanarFOA": ["-sba", "-1"], + "PlanarHOA2": ["-sba", "-2"], + "PlanarHOA3": ["-sba", "-3"], + "ISM1": ["-ism", "1"], + "ISM2": ["-ism", "2"], + "ISM3": ["-ism", "3"], + "ISM4": ["-ism", "4"], + "MASA_1TC_1DIR": ["-masa", "1"], + "MASA_2TC_1DIR": ["-masa", "2"], + "MASA_1TC_2DIR": ["-masa", "1"], + "MASA_2TC_2DIR": ["-masa", "2"], + "OMASA": ["-ism_masa"], + "OSBA": ["-ism_sba"], + "STEREO_DMX_EVS": ["-stereo_dmx_evs"], +} + +### Test case parameters + +# Input format IDs +INPUT_FORMATS_MC = ["MC_5_1", "MC_5_1_2", "MC_5_1_4", "MC_7_1", "MC_7_1_4"] +INPUT_FORMATS_CHANNEL_BASED = ["STEREO"] + INPUT_FORMATS_MC +INPUT_FORMATS_SCENE_BASED = [ + "FOA", + "HOA2", + "HOA3", + "PlanarFOA", + "PlanarHOA2", + "PlanarHOA3", +] +INPUT_FORMATS_OBJECT_BASED = ["ISM1", "ISM2", "ISM3", "ISM4"] +INPUT_FORMATS_MASA = [ + "MASA_1TC_1DIR", + "MASA_2TC_1DIR", + "MASA_1TC_2DIR", + "MASA_2TC_2DIR", +] + +BITRATES_ALL = [ + 13200, + 16400, + 24400, + 32000, + 48000, + 64000, + 80000, + 96000, + 128000, + 160000, + 192000, + 256000, + 384000, + 512000, +] +BITRATES_STEREO = bitrates_between(13200, 256000) +BITRATES_ISM1 = bitrates_between(13200, 128000) +BITRATES_ISM2 = bitrates_between(16400, 256000) +BITRATES_ISM3 = bitrates_between(24400, 384000) +BITRATES_ISM4 = bitrates_between(24400, 512000) +BITRATES_ISM1_EXTENDED = [b for b in BITRATES_ISM1 if b > 64000] +BITRATES_ISM2_EXTENDED = [b for b in BITRATES_ISM2 if b > 64000] +BITRATES_ISM3_EXTENDED = [b for b in BITRATES_ISM3 if b > 64000] +BITRATES_ISM4_EXTENDED = [b for b in BITRATES_ISM4 if b > 64000] +BITRATES_EVS = [5900, 7200, 8000, 9600] + BITRATES_ALL[:6] + BITRATES_ALL[7:9] + +SAMPLING_RATES_ALL = [16, 32, 48] +MAX_BAND_ALL = ["WB", "SWB", "FB"] + +OUTPUT_FORMATS_ALL = [ + "MONO", + "STEREO", + "5_1", + "5_1_2", + "5_1_4", + "7_1", + "7_1_4", + "FOA", + "HOA2", + "HOA3", + "EXT", + "BINAURAL", + "BINAURAL_ROOM_IR", + "BINAURAL_ROOM_REVERB", +] +OUTPUT_FORMATS_BINAURAL = OUTPUT_FORMATS_ALL[-3:] +OUTPUT_FORMATS_NON_BINAURAL = OUTPUT_FORMATS_ALL[:11] + + +### -------------- encoder parameter lists -------------- + +STEREO_PARAMS = list(product(["STEREO"], BITRATES_STEREO, [DTX_OFF, DTX_ON])) +MC_PARAMS = list(product(INPUT_FORMATS_MC, BITRATES_ALL, [DTX_OFF])) +MASA_PARAMS = list(product(INPUT_FORMATS_MASA, BITRATES_ALL, [DTX_OFF, DTX_ON])) +ENCODER_CHANNEL_BASED_AND_MASA_PARAMS = STEREO_PARAMS + MC_PARAMS + MASA_PARAMS + + +# ISM modes with three "flavours" of metadata +# different ranges of bitrates allowed depending on number of objects, ext MD only for >64kbps +ISM1_BASIC_NULL_PARAMS = list( + product( + ["ISM1"], + BITRATES_ISM1, + [DTX_OFF, DTX_ON], + [ISM_MD_BASIC, ISM_MD_NULL], + ) +) +ISM2_BASIC_NULL_PARAMS = list( + product( + ["ISM2"], + BITRATES_ISM2, + [DTX_OFF, DTX_ON], + [ISM_MD_BASIC, ISM_MD_NULL], + ) +) +ISM3_BASIC_NULL_PARAMS = list( + product( + ["ISM3"], + BITRATES_ISM3, + [DTX_OFF, DTX_ON], + [ISM_MD_BASIC, ISM_MD_NULL], + ) +) +ISM4_BASIC_NULL_PARAMS = list( + product( + ["ISM4"], + BITRATES_ISM4, + [DTX_OFF, DTX_ON], + [ISM_MD_BASIC, ISM_MD_NULL], + ) +) +ISM1_EXTENDED_PARAMS = list( + product( + ["ISM1"], + BITRATES_ISM1_EXTENDED, + [DTX_OFF, DTX_ON], + [ISM_MD_EXTENDED], + ) +) +ISM2_EXTENDED_PARAMS = list( + product( + ["ISM2"], + BITRATES_ISM2_EXTENDED, + [DTX_OFF, DTX_ON], + [ISM_MD_EXTENDED], + ) +) +ISM3_EXTENDED_PARAMS = list( + product( + ["ISM3"], + BITRATES_ISM3_EXTENDED, + [DTX_OFF, DTX_ON], + [ISM_MD_EXTENDED], + ) +) +ISM4_EXTENDED_PARAMS = list( + product( + ["ISM4"], + BITRATES_ISM4_EXTENDED, + [DTX_OFF, DTX_ON], + [ISM_MD_EXTENDED], + ) +) +ISM_PARAMS = ( + ISM1_BASIC_NULL_PARAMS + + ISM2_BASIC_NULL_PARAMS + + ISM3_BASIC_NULL_PARAMS + + ISM4_BASIC_NULL_PARAMS + + ISM1_EXTENDED_PARAMS + + ISM2_EXTENDED_PARAMS + + ISM3_EXTENDED_PARAMS + + ISM4_EXTENDED_PARAMS +) + + +# dtx only allowed at low bitrates, PCA only at FOA 256kbps +SBA_LOW_BITRATES_PARAMS = list( + ( + product( + INPUT_FORMATS_SCENE_BASED, + BITRATES_ALL[:7], + [DTX_OFF, DTX_ON], + [SBA_FOA_PCA_OFF], + ) + ) +) +SBA_HIGH_BITRATES_PARAMS = list( + ( + product( + INPUT_FORMATS_SCENE_BASED, + BITRATES_ALL[7:], + [DTX_OFF], + [SBA_FOA_PCA_OFF], + ) + ) +) +SBA_FOA_PCA_PARAMS = list( + product( + [f for f in INPUT_FORMATS_SCENE_BASED if "FOA" in f], + [256000], + [DTX_OFF], + [SBA_FOA_PCA_ON], + ) +) +SBA_PARAMS = SBA_LOW_BITRATES_PARAMS + SBA_HIGH_BITRATES_PARAMS + SBA_FOA_PCA_PARAMS + + +# All EVS bitrates, 5900 VBR always needs -dtx +STEREO_DMX_EVS_PARAMS = list(product(BITRATES_EVS[1:], [DTX_OFF, DTX_ON])) + list( + product(BITRATES_EVS[:1], [DTX_ON]) +) + + +OSBA_PARAMS = list( + product( + INPUT_FORMATS_OBJECT_BASED, + [ + f for f in INPUT_FORMATS_SCENE_BASED if not f.startswith("Planar") + ], # TODO: enable planar once clarified + BITRATES_ALL, + [ISM_MD_BASIC, ISM_MD_NULL, ISM_MD_EXTENDED], + ) +) +OMASA_PARAMS = list( + product( + INPUT_FORMATS_OBJECT_BASED, + INPUT_FORMATS_MASA, + BITRATES_ALL, + [ISM_MD_BASIC, ISM_MD_NULL, ISM_MD_EXTENDED], + ) +) +COMBINED_FORMATS_PARAMS = OSBA_PARAMS + OMASA_PARAMS + + +### -------------- decoder parameter lists -------------- + +BS_PROC_NONE = "CLEAN_CHANNEL" +BS_PROC_FER_15 = "FER_15perc" +BS_PROC_JBM_DLY_PROF_5 = "JBM_dlyprofile5" +BITSTREAM_PROCESSING = [BS_PROC_NONE, BS_PROC_FER_15, BS_PROC_JBM_DLY_PROF_5] + +# parameters for const bitrate test with non-binaural output +DECODER_CONST_BR_NO_BINAURAL_CHANNELBASED_AND_MASA = ( + collapse_into_list_of_pairs( + product( + STEREO_PARAMS, + OUTPUT_FORMATS_ALL[:7], + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + ) + ) + + collapse_into_list_of_pairs( + product( + MC_PARAMS, + OUTPUT_FORMATS_ALL[:10], + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + ) + ) + + collapse_into_list_of_pairs( + product( + MASA_PARAMS, + OUTPUT_FORMATS_NON_BINAURAL, + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + ) + ) +) +DECODER_CONST_BR_NO_BINAURAL_OBJECTBASED = collapse_into_list_of_pairs( + product( + ISM_PARAMS, + OUTPUT_FORMATS_NON_BINAURAL, + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + ) +) +DECODER_CONST_BR_NO_BINAURAL_SCENEBASED = collapse_into_list_of_pairs( + product( + SBA_PARAMS, + OUTPUT_FORMATS_NON_BINAURAL[:10], # one less to exclude EXT + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + ) +) +DECODER_CONST_BR_NO_BINAURAL_COMBINED_PARAMS = collapse_into_list_of_pairs( + product( + COMBINED_FORMATS_PARAMS, + OUTPUT_FORMATS_NON_BINAURAL[:10], # one less to exclude EXT + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING[:2], # TODO: re-add JBM once fully functional + ) +) + + +# parameters for const bitrate testcases with binaural output + +BINAURAL_HRTF_NONE = "HRTFdefault" +BINAURAL_HRTF_EXT_REPO = "HRFText_repo" +HRTF_PATHS = { + BINAURAL_HRTF_EXT_REPO: get_file_from_repo( + "scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_{fs}kHz.bin" + ) +} + +# TODO: all the following binaural rendering parameters are takenfrom selftest for now -> would need to create critical ones +OTR_NONE = "OTRnone" +OTR_REF = "OTRref" +OTR_AVG = "OTRavg" +OTR_REF_VEC = "OTRref_vec" +OTR_REF_VEC_LEV = "OTRref_vec_lev" +OTR_OPTIONS = { + OTR_NONE: list(), + OTR_REF: ["-otr", "ref", "-rf", get_file_from_repo("scripts/testv/headrot.csv")], + OTR_AVG: ["-otr", "avg"], + OTR_REF_VEC: [ + "-otr", + "ref_vec", + "-rvf", + get_file_from_repo("scripts/trajectories/full-circle-4s-Vector3.csv"), + ], + OTR_REF_VEC_LEV: [ + "-otr", + "ref_vec_lev", + "-rvf", + get_file_from_repo( + "scripts/trajectories/full-circle-with-up-and-down-4s-Vector3.csv" + ), + ], +} +HEAD_ROTATION_OPTIONS = { + OTR_NONE: ["-t", get_file_from_repo("scripts/testv/headrot.csv")], + OTR_REF: ["-t", get_file_from_repo("scripts/testv/headrot.csv")], + OTR_REF_VEC: ["-t", get_file_from_repo("scripts/trajectories/full-circle-4s.csv")], + OTR_REF_VEC_LEV: [ + "-t", + get_file_from_repo("scripts/trajectories/full-circle-with-up-and-down-4s.csv"), + ], +} +OTR_PARAMS = [OTR_NONE, OTR_REF, OTR_AVG, OTR_REF_VEC, OTR_REF_VEC_LEV] +EXOF_OFF = "EXOF_off" +EXOF_ON = "EXOF_on" +EXOF_OPTIONS = [ + "-exof", + get_file_from_repo("scripts/testv/headrot_case00_3000_q_combinedRotationTest.csv"), +] +EXOF_PARAMS = [EXOF_OFF, EXOF_ON] + +RENDER_CONFIG_ER_LOW_COMPLEXITY = "RC_low" +RENDER_CONFIG_ER_HIGH_COMPLEXITY = "RC_high" +RENDER_CONFIG_OPTIONS = { + RENDER_CONFIG_ER_LOW_COMPLEXITY: [ + "-render_config", + str(TESTV_PATH.joinpath("render_config1.cfg")), + ], + RENDER_CONFIG_ER_HIGH_COMPLEXITY: [ + "-render_config", + str(TESTV_PATH.joinpath("render_config2.cfg")), + ], +} +RENDER_CONFIG_PARAMS = [ + RENDER_CONFIG_ER_LOW_COMPLEXITY, + RENDER_CONFIG_ER_HIGH_COMPLEXITY, +] +DPID_OPTIONS = ["-dpid", "0", "1", "2", "3"] + +DECODER_CONST_BR_BINAURAL_MC_AND_MASA = collapse_into_list_of_pairs( + product( + MC_PARAMS, + OUTPUT_FORMATS_BINAURAL, + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + ) +) + collapse_into_list_of_pairs( + product( + MASA_PARAMS, + OUTPUT_FORMATS_BINAURAL, + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + ) +) +DECODER_CONST_BR_BINAURAL_OBJECTBASED = collapse_into_list_of_pairs( + product( + ISM_PARAMS, OUTPUT_FORMATS_BINAURAL, SAMPLING_RATES_ALL, BITSTREAM_PROCESSING + ) +) +DECODER_CONST_BR_BINAURAL_SCENEBASED = collapse_into_list_of_pairs( + product( + SBA_PARAMS, OUTPUT_FORMATS_BINAURAL, SAMPLING_RATES_ALL, BITSTREAM_PROCESSING + ) +) +DECODER_CONST_BR_BINAURAL_COMBINED_PARAMS = collapse_into_list_of_pairs( + product( + COMBINED_FORMATS_PARAMS, + OUTPUT_FORMATS_BINAURAL, + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + ) +) diff --git a/tests/codec_be_to_accepted_release/decoder/__init__.py b/tests/codec_be_to_accepted_release/decoder/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c567cf6d857aa9f9a21226a8c4eb3f90e6d951a9 --- /dev/null +++ b/tests/codec_be_to_accepted_release/decoder/__init__.py @@ -0,0 +1,237 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import numpy as np +import pytest +from contextlib import contextmanager +from pathlib import Path +from tempfile import TemporaryDirectory +import subprocess +from .. import is_be_to_ref, get_bitstream_path +from ..constants import ( + DUT_PATH, + REF_PATH, + TESTV_PATH, + HERE, + BS_PROC_FER_15, + BS_PROC_JBM_DLY_PROF_5, + BS_PROC_NONE, + BINAURAL_HRTF_NONE, + HRTF_PATHS, + OTR_OPTIONS, + HEAD_ROTATION_OPTIONS, + EXOF_OFF, + EXOF_ON, + EXOF_OPTIONS, + RENDER_CONFIG_OPTIONS, + DPID_OPTIONS, +) + + +def create_head_rotation_file( + trajectory: np.ndarray, + strategy: str, + switch_time: int, + length_frames: int, + axis: str = None, +): + assert strategy in ["from_array", "rotate_axis", "constant"] + + length_str = f"-l{length_frames}" if length_frames > 0 else "" + fname = f"head_rotation_trajectory-{strategy}-{switch_time}{length_str}" + + if strategy == "from_array": + rots = trajectory + elif strategy == "rotate_axis": + raise NotImplementedError("only idea for now") + elif strategy == "constant": + assert len(trajectory) == 1 + rots = np.repeat(trajectory, length_frames) + + out_path = DUT_PATH.joinpath(fname) + rots.astype(np.int32).tofile(out_path) + + return out_path + + +def get_output_path( + bitstream_path: Path, + output_format: str, + output_sampling_rate: int, + bitstream_processing: str, + is_ref_creation: bool, + suffix: str = "", +): + if suffix != "": + suffix = f"-{suffix}" + output_name = f"{bitstream_path.stem}.dec-{output_format}-{output_sampling_rate}kHz-{bitstream_processing}{suffix}.wav" + + output_folder = REF_PATH if is_ref_creation else DUT_PATH + return output_folder.joinpath(output_name) + + +@contextmanager +def get_bitstream_and_options( + testv_name, + encoder_format, + bitrate, + input_sampling_rate, + dtx, + processing, + max_band=None, + hrtf=BINAURAL_HRTF_NONE, + otr_mode=None, + suffix="", + non_diegetic_pan_value=None, + exof=EXOF_OFF, + render_config=None, + dpid=False, + output_sampling_rate=None + # TODO: keep for later when it is possible to use one unified render config file + # aeid=None, +): + """ + Utility to get either the stored reference bitstream or the processed version as a temporary file + + The reason for implementing this as a context manager instead of a simple function is that this way + the temporary processed bitstream files are cleaned up automatically and do not exploce disk space even more... + """ + options = ["-no_delay_cmp"] + with TemporaryDirectory() as tmp_dir: + # TODO: this should be coming from TESTV_PATH - current setuponly for development + bitstream = get_bitstream_path( + REF_PATH, + testv_name, + encoder_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + suffix, + ) + bitstream_out = Path(tmp_dir).joinpath(bitstream.stem + f".{processing}.192") + if processing == BS_PROC_FER_15: + ep_path = TESTV_PATH.joinpath("ltv_ep_015.192") + cmd = [ + # TODO: adapt for windows + "eid-xor", + "-fer", + "-vbr", + str(bitstream), + str(ep_path), + str(bitstream_out), + ] + subprocess.run(cmd) + bitstream = bitstream_out + elif processing == BS_PROC_JBM_DLY_PROF_5: + dly_profile_path = HERE.joinpath( + "../../scripts/dly_error_profiles/dly_error_profile_5.dat" + ) + tracefile_path = Path(tmp_dir).joinpath(bitstream_out.with_suffix(".trace")) + # TODO: adapt for windows + # TODO: get number of frames per packet from error profile name + cmd = [ + "networkSimulator_g192", + str(dly_profile_path), + str(bitstream), + str(bitstream_out), + str(tracefile_path), + "2", + "0", + ] + subprocess.run(cmd) + bitstream = bitstream_out + options.append("-VOIP") + + if hrtf != BINAURAL_HRTF_NONE: + assert output_sampling_rate is not None + options.extend(["-hrtf", str(HRTF_PATHS[hrtf]).format(fs=output_sampling_rate)]) + + if non_diegetic_pan_value is not None: + options.extend(["-non_diegetic_pan", f"{non_diegetic_pan_value}"]) + + if otr_mode is not None: + options.extend(HEAD_ROTATION_OPTIONS.get(otr_mode, list())) + options.extend(OTR_OPTIONS[otr_mode]) + + if exof == EXOF_ON: + options.extend(EXOF_OPTIONS) + + if render_config is not None: + options.extend(RENDER_CONFIG_OPTIONS[render_config]) + options.extend(["-aeid", "0"]) + + if dpid: + assert render_config + if encoder_format.startswith("ISM"): + n_ism = int(encoder_format[-1]) + elif encoder_format in ["OMASA", "OSBA"]: + # get number of isms from testv name + n_ism = int(testv_name.split("_")[2][0]) + else: + raise ValueError("dpid only for ISM and combined_formats") + + # +1 for the "-dpid" at index 0 + options.extend(DPID_OPTIONS[: n_ism + 1]) + + # if aeid is not None: + # options.extend(["-aeid", str(aeid)]) + + yield bitstream, options + + +def run_check( + ref_bitstream: Path, + output_format: str, + output_sampling_rate: int, + options: list, + decoder_frontend, + is_ref_creation: bool, + output_suffix="", + bitstream_processing=BS_PROC_NONE, +): + output_path = get_output_path( + ref_bitstream, + output_format, + output_sampling_rate, + bitstream_processing, + is_ref_creation, + suffix=output_suffix, + ) + decoder_frontend.run( + output_format, + output_sampling_rate, + ref_bitstream, + output_path, + add_option_list=options, + ) + + if not is_ref_creation and not is_be_to_ref(output_path): + pytest.fail(f"Decoder output differs from reference") diff --git a/tests/codec_be_to_accepted_release/decoder/test_decoder_constant_bitrate_binaural.py b/tests/codec_be_to_accepted_release/decoder/test_decoder_constant_bitrate_binaural.py new file mode 100644 index 0000000000000000000000000000000000000000..9bbebb8065b7d619dd54e60848ace7874f059242 --- /dev/null +++ b/tests/codec_be_to_accepted_release/decoder/test_decoder_constant_bitrate_binaural.py @@ -0,0 +1,234 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import pytest +from . import get_bitstream_and_options, run_check +from .. import get_testv_path, get_valid_fs_max_band_pairs +from ..constants import * + + +def pytest_generate_tests(metafunc): + # NOTE: this excludes narrow-band modes for stereo_dmx_evs as those are not really IVAS but EVS and implementation is complicated... + fs_mb_params = get_valid_fs_max_band_pairs() + metafunc.parametrize("input_sampling_rate,max_band", fs_mb_params) + + +@pytest.mark.parametrize("hrtf", [BINAURAL_HRTF_NONE, BINAURAL_HRTF_EXT_REPO]) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_MC_AND_MASA, +) +def test_decoder_mc_and_masa( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + output_format, + output_sampling_rate, + bitstream_processing, + hrtf, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + hrtf=hrtf, + output_sampling_rate=output_sampling_rate, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=hrtf, + bitstream_processing=bitstream_processing, + ) + + +@pytest.mark.parametrize("hrtf", [BINAURAL_HRTF_NONE, BINAURAL_HRTF_EXT_REPO]) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,md_type,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_OBJECTBASED, +) +def test_decoder_objectbased( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + hrtf, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + suffix=suffix, + hrtf=hrtf, + output_sampling_rate=output_sampling_rate, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=hrtf, + bitstream_processing=bitstream_processing, + ) + + +@pytest.mark.parametrize("hrtf", [BINAURAL_HRTF_NONE, BINAURAL_HRTF_EXT_REPO]) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,pca,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_SCENEBASED, +) +def test_decoder_scenebased( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + pca, + output_format, + output_sampling_rate, + bitstream_processing, + hrtf, + dut_decoder_frontend, + update_ref, +): + # TODO: remove once fixed + if input_format == "PlanarFOA" and bitstream_processing == BS_PROC_JBM_DLY_PROF_5: + pytest.skip("PlanarFOA and JBM currently crashes") + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "" + if pca == SBA_FOA_PCA_ON: + suffix += "-pca" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + suffix=suffix, + hrtf=hrtf, + output_sampling_rate=output_sampling_rate, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=hrtf, + bitstream_processing=bitstream_processing, + ) + + +@pytest.mark.parametrize("hrtf", [BINAURAL_HRTF_NONE, BINAURAL_HRTF_EXT_REPO]) +@pytest.mark.parametrize( + "input_format_ism,input_format_other,bitrate,md_type,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_COMBINED_PARAMS, +) +def test_decoder_combined_formats( + input_format_ism, + input_format_other, + bitrate, + input_sampling_rate, + max_band, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + hrtf, + dut_decoder_frontend, + update_ref, +): + input_format_combined = "OMASA" if "MASA" in input_format_other else "OSBA" + testv_name = get_testv_path( + f"{input_format_combined}_{input_format_ism}_{input_format_other}", + input_sampling_rate, + ).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format_combined, + bitrate, + input_sampling_rate, + DTX_OFF, + suffix=suffix, + hrtf=hrtf, + output_sampling_rate=output_sampling_rate, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=hrtf, + bitstream_processing=bitstream_processing, + ) diff --git a/tests/codec_be_to_accepted_release/decoder/test_decoder_constant_bitrate_no_binaural.py b/tests/codec_be_to_accepted_release/decoder/test_decoder_constant_bitrate_no_binaural.py new file mode 100644 index 0000000000000000000000000000000000000000..0ac17f72b21c5e9f097dfb1fab102a06bde08601 --- /dev/null +++ b/tests/codec_be_to_accepted_release/decoder/test_decoder_constant_bitrate_no_binaural.py @@ -0,0 +1,214 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import pytest +from . import get_bitstream_and_options, run_check +from .. import get_testv_path, get_valid_fs_max_band_pairs +from ..constants import * + + +def pytest_generate_tests(metafunc): + # NOTE: this excludes narrow-band modes for stereo_dmx_evs as those are not really IVAS but EVS and implementation is complicated... + fs_mb_params = get_valid_fs_max_band_pairs() + metafunc.parametrize("input_sampling_rate,max_band", fs_mb_params) + + +@pytest.mark.parametrize( + "input_format,bitrate,dtx,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_NO_BINAURAL_CHANNELBASED_AND_MASA, +) +def test_decoder_channelbased_and_masa( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + output_format, + output_sampling_rate, + bitstream_processing, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + bitstream_processing=bitstream_processing, + ) + + +@pytest.mark.parametrize( + "input_format,bitrate,dtx,md_type,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_NO_BINAURAL_OBJECTBASED, +) +def test_decoder_objectbased( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + suffix=suffix, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + bitstream_processing=bitstream_processing, + ) + + +@pytest.mark.parametrize( + "input_format,bitrate,dtx,pca,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_NO_BINAURAL_SCENEBASED, +) +def test_decoder_scenebased( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + pca, + output_format, + output_sampling_rate, + bitstream_processing, + dut_decoder_frontend, + update_ref, +): + # TODO: remove once fixed + if input_format == "PlanarFOA" and bitstream_processing == BS_PROC_JBM_DLY_PROF_5: + pytest.skip("PlanarFOA and JBM currently crashes") + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "" + if pca == SBA_FOA_PCA_ON: + suffix += "-pca" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + suffix=suffix, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + bitstream_processing=bitstream_processing, + ) + + +@pytest.mark.parametrize( + "input_format_ism,input_format_other,bitrate,md_type,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_NO_BINAURAL_COMBINED_PARAMS, +) +def test_decoder_combined_formats( + input_format_ism, + input_format_other, + bitrate, + input_sampling_rate, + max_band, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + dut_decoder_frontend, + update_ref, +): + input_format_combined = "OMASA" if "MASA" in input_format_other else "OSBA" + testv_name = get_testv_path( + f"{input_format_combined}_{input_format_ism}_{input_format_other}", + input_sampling_rate, + ).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format_combined, + bitrate, + input_sampling_rate, + DTX_OFF, + suffix=suffix, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + bitstream_processing=bitstream_processing, + ) diff --git a/tests/codec_be_to_accepted_release/decoder/test_decoder_head_rotation.py b/tests/codec_be_to_accepted_release/decoder/test_decoder_head_rotation.py new file mode 100644 index 0000000000000000000000000000000000000000..0ce4f363a6a92e12ed07986fc923a6d254429a18 --- /dev/null +++ b/tests/codec_be_to_accepted_release/decoder/test_decoder_head_rotation.py @@ -0,0 +1,241 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import pytest +from . import get_bitstream_and_options, run_check +from .. import get_testv_path, get_valid_fs_max_band_pairs +from ..constants import * + + +def pytest_generate_tests(metafunc): + # NOTE: this excludes narrow-band modes for stereo_dmx_evs as those are not really IVAS but EVS and implementation is complicated... + fs_mb_params = get_valid_fs_max_band_pairs() + metafunc.parametrize("input_sampling_rate,max_band", fs_mb_params) + + +@pytest.mark.parametrize("exof", EXOF_PARAMS) +@pytest.mark.parametrize("otr_mode", OTR_PARAMS) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_MC_AND_MASA, +) +def test_decoder_hr_mc_and_masa( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + output_format, + output_sampling_rate, + bitstream_processing, + otr_mode, + exof, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + processing=bitstream_processing, + otr_mode=otr_mode, + exof=exof, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + bitstream_processing=bitstream_processing, + output_suffix=f"{otr_mode}-{exof}", + ) + + +# NOTE: md_type probably does not need to be exhaustively tested in combination with OTR +# NOTE: same for FER/JBM +@pytest.mark.parametrize("exof", EXOF_PARAMS) +@pytest.mark.parametrize("otr_mode", OTR_PARAMS) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,md_type,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_OBJECTBASED, +) +def test_decoder_hr_objectbased( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + otr_mode, + exof, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + suffix=suffix, + processing=bitstream_processing, + otr_mode=otr_mode, + exof=exof, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + bitstream_processing=bitstream_processing, + output_suffix=f"{otr_mode}-{exof}", + ) + + +@pytest.mark.parametrize("exof", EXOF_PARAMS) +@pytest.mark.parametrize("otr_mode", OTR_PARAMS) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,pca,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_SCENEBASED, +) +def test_decoder_hr_scenebased( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + pca, + output_format, + output_sampling_rate, + bitstream_processing, + otr_mode, + exof, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "" + if pca == SBA_FOA_PCA_ON: + suffix += "-pca" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + suffix=suffix, + processing=bitstream_processing, + otr_mode=otr_mode, + exof=exof, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + bitstream_processing=bitstream_processing, + output_suffix=f"{otr_mode}-{exof}", + ) + + +@pytest.mark.parametrize("exof", EXOF_PARAMS) +@pytest.mark.parametrize("otr_mode", OTR_PARAMS) +@pytest.mark.parametrize( + "input_format_ism,input_format_other,bitrate,md_type,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_COMBINED_PARAMS, +) +def test_decoder_hr_combined_formats( + input_format_ism, + input_format_other, + bitrate, + input_sampling_rate, + max_band, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + otr_mode, + exof, + dut_decoder_frontend, + update_ref, +): + input_format_combined = "OMASA" if "MASA" in input_format_other else "OSBA" + testv_name = get_testv_path( + f"{input_format_combined}_{input_format_ism}_{input_format_other}", + input_sampling_rate, + ).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format_combined, + bitrate, + input_sampling_rate, + DTX_OFF, + suffix=suffix, + processing=bitstream_processing, + otr_mode=otr_mode, + exof=exof, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + bitstream_processing=bitstream_processing, + output_suffix=f"{otr_mode}-{exof}", + ) diff --git a/tests/codec_be_to_accepted_release/decoder/test_decoder_non_diegetic_pan.py b/tests/codec_be_to_accepted_release/decoder/test_decoder_non_diegetic_pan.py new file mode 100644 index 0000000000000000000000000000000000000000..2d0b91e275cf3810eb0c60d92edf385e23d64ac2 --- /dev/null +++ b/tests/codec_be_to_accepted_release/decoder/test_decoder_non_diegetic_pan.py @@ -0,0 +1,148 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import pytest +from . import get_bitstream_and_options, run_check +from .. import get_testv_path, get_valid_fs_max_band_pairs +from ..constants import ( + STEREO_DMX_EVS_PARAMS, + ISM_MD_EXTENDED, + ISM_MD_NULL, + DECODER_CONST_BR_NO_BINAURAL_OBJECTBASED, + SAMPLING_RATES_ALL, + BITSTREAM_PROCESSING, + SAMPLING_RATES_ALL, +) + + +def pytest_generate_tests(metafunc): + # NOTE: this excludes narrow-band modes for stereo_dmx_evs as those are not really IVAS but EVS and implementation is complicated... + fs_mb_params = get_valid_fs_max_band_pairs() + metafunc.parametrize("input_sampling_rate,max_band", fs_mb_params) + + +# NOTE: this way, all possible inputs for the non-diegetic panning value are used for all input/output configs +# less exhaustive testing is probably enough here, one can e.g. only test one panning value for each i/o config +NON_DIEGETIC_PAN_VALUES = ["c", "center", "middle", "left", "l", "right", "r"] + list( + range(-90, 91) +) +ISM1_DECODER_PARAMS = [ + p + for p in DECODER_CONST_BR_NO_BINAURAL_OBJECTBASED + if p[0].startswith("ISM1") and p[1] == "STEREO" +] + + +@pytest.mark.parametrize("non_diegetic_panning_value", NON_DIEGETIC_PAN_VALUES) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,md_type,output_format,output_sampling_rate,bitstream_processing", + ISM1_DECODER_PARAMS, +) +def test_decoder_non_diegetic_pan_ism( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + non_diegetic_panning_value, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + bitstream_processing, + suffix=suffix, + max_band=max_band, + ) as (ref_bitstream, options): + suffix += f"-non_diegetic_pan_{non_diegetic_panning_value}" + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=suffix, + bitstream_processing=bitstream_processing, + ) + + +# for the mono input, we use the Stereo DMX EVS outputs from the decoder so no explicit mono encoder run is needed +@pytest.mark.parametrize("non_diegetic_panning_value", NON_DIEGETIC_PAN_VALUES) +@pytest.mark.parametrize("bitrate,dtx", STEREO_DMX_EVS_PARAMS) +@pytest.mark.parametrize("output_sampling_rate", SAMPLING_RATES_ALL) +@pytest.mark.parametrize("bitstream_processing", BITSTREAM_PROCESSING) +def test_decoder_non_diegetic_pan_mono( + bitrate, + input_sampling_rate, + max_band, + dtx, + output_sampling_rate, + bitstream_processing, + non_diegetic_panning_value, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path("STEREO", input_sampling_rate).stem + with get_bitstream_and_options( + testv_name, + "StereoDmxEvs", + bitrate, + input_sampling_rate, + dtx, + bitstream_processing, + non_diegetic_pan_value=non_diegetic_panning_value, + max_band=max_band, + ) as (ref_bitstream, options): + suffix = f"-non_diegetic_pan_{non_diegetic_panning_value}" + run_check( + ref_bitstream, + "", + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=suffix, + bitstream_processing=bitstream_processing, + ) diff --git a/tests/codec_be_to_accepted_release/decoder/test_decoder_render_config.py b/tests/codec_be_to_accepted_release/decoder/test_decoder_render_config.py new file mode 100644 index 0000000000000000000000000000000000000000..50e872c28c2dd3eb38ca07bcc2930e1b1659b3d5 --- /dev/null +++ b/tests/codec_be_to_accepted_release/decoder/test_decoder_render_config.py @@ -0,0 +1,244 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import pytest +from . import get_bitstream_and_options, run_check +from .. import get_testv_path, get_valid_fs_max_band_pairs +from ..constants import * + + +def pytest_generate_tests(metafunc): + # NOTE: this excludes narrow-band modes for stereo_dmx_evs as those are not really IVAS but EVS and implementation is complicated... + fs_mb_params = get_valid_fs_max_band_pairs() + metafunc.parametrize("input_sampling_rate,max_band", fs_mb_params) + + +@pytest.mark.parametrize("render_config", RENDER_CONFIG_PARAMS) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,md_type,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_OBJECTBASED, +) +def test_decoder_objectbased_render_conf_directivity( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + render_config, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + suffix=suffix, + processing=bitstream_processing, + dpid=True, + render_config=render_config, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=f"dpid-{render_config}", + bitstream_processing=bitstream_processing, + ) + + +@pytest.mark.parametrize("render_config", RENDER_CONFIG_PARAMS) +@pytest.mark.parametrize( + "input_format_ism,input_format_other,bitrate,md_type,output_format,output_sampling_rate,bitstream_processing", + DECODER_CONST_BR_BINAURAL_COMBINED_PARAMS, +) +def test_decoder_combined_formats_render_conf_directivity( + input_format_ism, + input_format_other, + bitrate, + input_sampling_rate, + max_band, + md_type, + output_format, + output_sampling_rate, + bitstream_processing, + render_config, + dut_decoder_frontend, + update_ref, +): + input_format_combined = "OMASA" if "MASA" in input_format_other else "OSBA" + testv_name = get_testv_path( + f"{input_format_combined}_{input_format_ism}_{input_format_other}", + input_sampling_rate, + ).stem + suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + suffix = "_null_MD" + with get_bitstream_and_options( + testv_name, + input_format_combined, + bitrate, + input_sampling_rate, + DTX_OFF, + suffix=suffix, + processing=bitstream_processing, + render_config=render_config, + dpid=True, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=f"dpid-{render_config}", + bitstream_processing=bitstream_processing, + ) + + +# all non-ISM modes can not use directivity parts from the render config +# we only need the REVERB output config for the AE parts + + +@pytest.mark.parametrize("render_config", RENDER_CONFIG_PARAMS) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,output_format,output_sampling_rate,bitstream_processing", + [ + params + for params in DECODER_CONST_BR_BINAURAL_MC_AND_MASA + if params[4] == "BINAURAL_ROOM_REVERB" + ], +) +def test_decoder_mc_and_masa_render_conf( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + output_format, + output_sampling_rate, + bitstream_processing, + render_config, + dut_decoder_frontend, + update_ref, +): + testv_name = get_testv_path(input_format, input_sampling_rate).stem + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + render_config=render_config, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=f"{render_config}", + bitstream_processing=bitstream_processing, + ) + + +@pytest.mark.parametrize("render_config", RENDER_CONFIG_PARAMS) +@pytest.mark.parametrize( + "input_format,bitrate,dtx,pca,output_format,output_sampling_rate,bitstream_processing", + [ + params + for params in DECODER_CONST_BR_BINAURAL_SCENEBASED + if params[5] == "BINAURAL_ROOM_REVERB" + ], +) +def test_decoder_scenebased_render_conf( + input_format, + bitrate, + input_sampling_rate, + max_band, + dtx, + pca, + output_format, + output_sampling_rate, + bitstream_processing, + render_config, + dut_decoder_frontend, + update_ref, +): + # TODO: remove once fixed + if input_format == "PlanarFOA" and bitstream_processing == BS_PROC_JBM_DLY_PROF_5: + pytest.skip("PlanarFOA and JBM currently crashes") + testv_name = get_testv_path(input_format, input_sampling_rate).stem + suffix = "" + if pca == SBA_FOA_PCA_ON: + suffix += "-pca" + with get_bitstream_and_options( + testv_name, + input_format, + bitrate, + input_sampling_rate, + dtx, + suffix=suffix, + render_config=render_config, + processing=bitstream_processing, + max_band=max_band, + ) as (ref_bitstream, options): + run_check( + ref_bitstream, + output_format, + output_sampling_rate, + options, + dut_decoder_frontend, + update_ref == 1, + output_suffix=f"{render_config}", + bitstream_processing=bitstream_processing, + ) diff --git a/tests/codec_be_to_accepted_release/encoder/__init__.py b/tests/codec_be_to_accepted_release/encoder/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..83137cd7c274263994472c83144847c4b241d14c --- /dev/null +++ b/tests/codec_be_to_accepted_release/encoder/__init__.py @@ -0,0 +1,190 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import numpy as np +import random +import pytest +from itertools import permutations +from .. import is_be_to_ref, get_bitstream_path +from ..constants import ( + METADATA_FOR_INPUT_FORMAT, + ISM_MD_NULL, + CMDL_OPTIONS_FOR_INPUT_FORMAT, + ISM_MD_EXTENDED, + INPUT_FORMATS_OBJECT_BASED, + DUT_PATH, + TESTV_PATH, + REF_PATH, + DTX_ON, + INPUT_FORMATS_SCENE_BASED, + INPUT_FORMATS_MASA, +) + + +def create_br_switching_file( + bitrates: np.ndarray, + strategy: str, + switch_time: int = 1, + length_frames: int = 0, + seed: int = None, +): + """ + Create bitrate switching pattern files on the fly and return path to it + + bitrates - array of bitrate values to include + strategy - how to create pattern: + "from_array" - use given array as is + "exhaustive" - generate array where every bitrate is preceeded and followed at least once by every other bitrate + "random" - randomly pick from bitrates + switch_time - number of frames before next switch + length_frames - for "random" strategy: length of pattern in frames + seed - for "exhaustive" and "random" strategies: inject seed for shuffling/choosing from array + """ + assert strategy in ["from_array", "exhaustive", "random"] + + seed_str = f"_{seed}" if strategy == "random" or strategy == "exhaustive" else "" + length_str = f"-l{length_frames}" if length_frames > 0 else "" + fname = f"br_sw_pattern-{strategy}{seed_str}-{switch_time}{length_str}" + + # TODO: maybe calculate seed based on given parameter to automatically have reproducibility + if seed is not None: + random.seed(seed) + + if strategy == "from_array": + brs = bitrates + elif strategy == "exhaustive": + # TODO: review, probably needs more work to be really exhaustive... + n = len(brs) - 1 + permuts = list(permutations(bitrates, 2)) + split_permuts = [permuts[i * n : (i + 1) * n] for i in range(len(brs))] + for i in range(len(split_permuts)): + random.shuffle(split_permuts[i]) + split_permuts = np.asarray(split_permuts) + brs = np.concatenate([split_permuts[:, i] for i in range(n)]) + elif strategy == "random": + brs = np.asarray(random.choices(bitrates, k=length_frames)) + + brs = np.repeat(brs, switch_time).astype(np.int32) + + out_path = DUT_PATH.joinpath(fname) + brs.tofile(out_path) + + return out_path + + +def get_md(input_format, md_type=None): + md_files = METADATA_FOR_INPUT_FORMAT.get(input_format, list()) + if md_type == ISM_MD_NULL: + md_files = ["NULL" for f in md_files] + else: + md_files = [str(TESTV_PATH.joinpath(f)) for f in md_files] + return md_files + + +def get_options(input_format_1, input_format_2=None, max_band=None, md_type=None): + + print(input_format_1) + options = list(CMDL_OPTIONS_FOR_INPUT_FORMAT[input_format_1]) + print(options) + + if md_type == ISM_MD_EXTENDED: + assert input_format_1 in INPUT_FORMATS_OBJECT_BASED + options[1] = f"+{options[1]}" + + md_options = get_md(input_format_1, md_type) + + # this block is for the combined formats only + if input_format_2 is not None: + options_other = list(CMDL_OPTIONS_FOR_INPUT_FORMAT.get(input_format_2, list())) + + input_format_combined = None + if input_format_2 in INPUT_FORMATS_SCENE_BASED: + input_format_combined = "OSBA" + elif input_format_2 in INPUT_FORMATS_MASA: + input_format_combined = "OMASA" + + options_combined = list(CMDL_OPTIONS_FOR_INPUT_FORMAT.get(input_format_combined, list())) + + # add MASA MD files for OMASA modes + md_options += get_md(input_format_2) + + options = options_combined + options[1:2] + options_other[1:2] + md_options + + else: + options.extend(md_options) + + if max_band is not None: + options.insert(0, "-max_band") + options.insert(1, max_band) + + options.insert(0, "-no_delay_cmp") + + print(options) + + return options + + +def run_check( + input_format, + bitrate, + sampling_rate, + testv, + options, + encoder_frontend, + is_ref_creation, + dtx, + bitstream_suffix="", +): + bs_path = REF_PATH if is_ref_creation else DUT_PATH + + max_band = options[options.index("-max_band") + 1] + + bitstream = get_bitstream_path( + bs_path, + testv.stem, + input_format, + bitrate, + sampling_rate, + max_band, + dtx, + suffix=bitstream_suffix, + ) + print(options) + encoder_frontend.run( + bitrate, + sampling_rate, + testv, + bitstream, + dtx_mode=dtx == DTX_ON, + add_option_list=options, + ) + + if not is_ref_creation and not is_be_to_ref(bitstream): + pytest.fail(f"Bitstream file differs from reference") diff --git a/tests/codec_be_to_accepted_release/encoder/test_encoder_bitrate_switching.py b/tests/codec_be_to_accepted_release/encoder/test_encoder_bitrate_switching.py new file mode 100644 index 0000000000000000000000000000000000000000..5e6e66824ed7fc057af50649be70c60f61aa34e5 --- /dev/null +++ b/tests/codec_be_to_accepted_release/encoder/test_encoder_bitrate_switching.py @@ -0,0 +1,63 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import pytest +from ..constants import * +from . import get_options, run_check, create_br_switching_file +from .. import get_testv_path, get_bitstream_path + + +@pytest.mark.skip("not ready, comitted by accident") +@pytest.mark.parametrize( + "input_format,bitrate,sampling_rate,dtx", ENCODER_CHANNEL_BASED_AND_MASA_PARAMS +) +def test_encoder_br_switching_channel_based_and_masa_modes( + input_format, + bitrate, + sampling_rate, + dtx, + dut_encoder_frontend, + update_ref, +): + testv = get_testv_path(input_format, sampling_rate) + options = get_options(input_format) + bitstream = get_bitstream_path( + DUT_PATH, testv.stem, input_format, bitrate, sampling_rate, dtx + ) + run_check( + bitstream, + bitrate, + sampling_rate, + testv, + options, + dut_encoder_frontend, + update_ref == 1, + dtx == DTX_ON, + ) diff --git a/tests/codec_be_to_accepted_release/encoder/test_encoder_constant_bitrate.py b/tests/codec_be_to_accepted_release/encoder/test_encoder_constant_bitrate.py new file mode 100644 index 0000000000000000000000000000000000000000..25111dfa39f03f25d5e2ee2e25ac7fa601f774d4 --- /dev/null +++ b/tests/codec_be_to_accepted_release/encoder/test_encoder_constant_bitrate.py @@ -0,0 +1,221 @@ +__copyright__ = """ +(C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +import itertools +import random +from ..constants import ( + ISM_MD_NULL, + ISM_MD_EXTENDED, + ENCODER_CHANNEL_BASED_AND_MASA_PARAMS, + DTX_OFF, + ISM_PARAMS, + SBA_PARAMS, + SBA_FOA_PCA_ON, + STEREO_DMX_EVS_PARAMS, + COMBINED_FORMATS_PARAMS, +) +from . import get_options, run_check +from .. import get_testv_path, get_valid_fs_max_band_pairs + + +TEST_PARAMS_EXHAUSTIVE = { + "test_encoder_const_br_channel_based_and_masa_modes": ( + "input_format,bitrate,dtx", + ENCODER_CHANNEL_BASED_AND_MASA_PARAMS, + ), + "test_encoder_const_br_object_based_modes": ( + "input_format,bitrate,dtx,md_type", + ISM_PARAMS, + ), + "test_encoder_const_br_scenebased": ("input_format,bitrate,dtx,pca", SBA_PARAMS), + "test_encoder_const_br_stereo_dmx_evs": ("bitrate,dtx", STEREO_DMX_EVS_PARAMS), + "test_encoder_const_br_combined_formats": ( + "input_format_ism,input_format_other,bitrate,md_type", + COMBINED_FORMATS_PARAMS, + ), +} + +N_PARAMS = {t: n for t, n in zip(TEST_PARAMS_EXHAUSTIVE.keys(), [40] * 5)} + + +def pytest_generate_tests(metafunc): + + func_name = metafunc.function.__name__ + param_string_fs_mb = "sampling_rate,max_band" + fs_mb_params = get_valid_fs_max_band_pairs() + param_string, params = TEST_PARAMS_EXHAUSTIVE[func_name] + + if metafunc.config.getoption("reduced"): + # randomly choose lower number of parameters + random.seed("IVAAAAS") + param_string = ",".join([param_string, param_string_fs_mb]) + combined_params = [p[0] + p[1] for p in itertools.product(params, fs_mb_params)] + metafunc.parametrize( + param_string, random.sample(combined_params, N_PARAMS[func_name]) + ) + else: + # NOTE: this excludes narrow-band modes for stereo_dmx_evs as those are not really IVAS but EVS and implementation is complicated... + metafunc.parametrize(param_string_fs_mb, fs_mb_params) + metafunc.parametrize(param_string, params) + + +# channel-based modes + MASA +def test_encoder_const_br_channel_based_and_masa_modes( + input_format, + bitrate, + sampling_rate, + max_band, + dtx, + dut_encoder_frontend, + update_ref, +): + testv = get_testv_path(input_format, sampling_rate) + options = get_options(input_format, max_band=max_band) + run_check( + input_format, + bitrate, + sampling_rate, + testv, + options, + dut_encoder_frontend, + update_ref == 1, + dtx, + ) + + +def test_encoder_const_br_object_based_modes( + input_format, + bitrate, + sampling_rate, + max_band, + dtx, + md_type, + dut_encoder_frontend, + update_ref, +): + testv = get_testv_path(input_format, sampling_rate) + options = get_options(input_format, max_band=max_band, md_type=md_type) + bitstream_suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + bitstream_suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + bitstream_suffix = "_null_MD" + run_check( + input_format, + bitrate, + sampling_rate, + testv, + options, + dut_encoder_frontend, + update_ref == 1, + dtx, + bitstream_suffix=bitstream_suffix, + ) + + +def test_encoder_const_br_scenebased( + input_format, + bitrate, + sampling_rate, + max_band, + dtx, + pca, + dut_encoder_frontend, + update_ref, +): + testv = get_testv_path(input_format, sampling_rate) + options = get_options(input_format, max_band=max_band) + bitstream_suffix = "" + if pca == SBA_FOA_PCA_ON: + options.extend(["-bypass", "2"]) + bitstream_suffix += "-pca" + run_check( + input_format, + bitrate, + sampling_rate, + testv, + options, + dut_encoder_frontend, + update_ref == 1, + dtx, + bitstream_suffix=bitstream_suffix, + ) + + +def test_encoder_const_br_stereo_dmx_evs( + bitrate, sampling_rate, max_band, dtx, dut_encoder_frontend, update_ref +): + testv = get_testv_path("STEREO", sampling_rate) + input_format = "STEREO_DMX_EVS" + options = get_options(input_format, max_band=max_band) + run_check( + input_format, + bitrate, + sampling_rate, + testv, + options, + dut_encoder_frontend, + update_ref == 1, + dtx, + ) + + +def test_encoder_const_br_combined_formats( + input_format_ism, + input_format_other, + bitrate, + sampling_rate, + max_band, + md_type, + dut_encoder_frontend, + update_ref, +): + input_format_combined = "OMASA" if "MASA" in input_format_other else "OSBA" + testv = get_testv_path( + f"{input_format_combined}_{input_format_ism}_{input_format_other}", + sampling_rate, + ) + options = get_options(input_format_ism, input_format_2=input_format_other, max_band=max_band, md_type=md_type) + bitstream_suffix = "_basic_MD" + if md_type == ISM_MD_EXTENDED: + bitstream_suffix = "_ext_MD" + elif md_type == ISM_MD_NULL: + bitstream_suffix = "_null_MD" + run_check( + input_format_combined, + bitrate, + sampling_rate, + testv, + options, + dut_encoder_frontend, + update_ref == 1, + DTX_OFF, + bitstream_suffix=bitstream_suffix, + ) diff --git a/tests/conftest.py b/tests/conftest.py index 3c6d18ceb339e677897d33aaedcf26ad5df29f13..44e811b4064f90a3c74213562cc84d4c86a99dce 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -151,6 +151,8 @@ def pytest_addoption(parser): help="Timeout in seconds for each individual testcase. Default is no timeout.", ) + parser.addoption("--reduced", action="store_true", help="Flag for running the allpairs-reduced version of the long BE test") + @pytest.fixture(scope="session", autouse=True) def update_ref(request): @@ -225,6 +227,7 @@ class EncoderFrontend: max_band: Optional[str] = None, bypass_mode: Optional[int] = None, quiet_mode: Optional[bool] = True, + dtx_update_rate: Optional[int] = None, add_option_list: Optional[list] = None, ) -> None: command = [self._path] @@ -234,7 +237,12 @@ class EncoderFrontend: command.extend(["-sba", sba_order]) if dtx_mode: - command.extend(["-dtx"]) + dtx_options = ["-dtx"] + if dtx_update_rate is not None: + if dtx_update_rate != 0 and not (dtx_update_rate in range(3, 101)): + raise ValueError(f"Invalid dtx update rate of {dtx_update_rate} given") + dtx_options.append(str(dtx_update_rate)) + command.extend(dtx_options) if max_band is not None: command.extend(["-max_band", max_band])