diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2a5cbb88b6e97b312c01a9843e59a2556bc7a2cb..2ab15a78b6a509b298de7190bb0717a92ea8e948 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -872,7 +872,7 @@ lc3-wrapper-unit-test: script: - cmake -B cmake-build -G "Unix Makefiles" -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - cmake --build cmake-build -- -j - - scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test + - scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test # compare split-rendering bitexactness between target and source branch split-rendering-pytest-on-merge-request: diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c5beb9a0d546fe2649575fe8110037314df6621..c2143c90900c12c534cc9abad40187d05e5928d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,7 +174,7 @@ target_include_directories(lib_util PUBLIC lib_util PRIVATE lib_com lib_enc lib_ target_include_directories(lib_util PRIVATE lib_lc3plus lib_isar) if(NOT WMOPS) - add_executable(ivas_lc3plus_unit_test scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c) + add_executable(ivas_lc3plus_unit_test scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test.c) target_link_libraries(ivas_lc3plus_unit_test lib_rend lib_dec lib_util lib_com lib_debug lib_isar) endif() @@ -213,7 +213,7 @@ if(COPY_EXECUTABLES_FROM_BUILD_DIR) add_custom_command(TARGET IVAS_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") add_custom_command(TARGET ISAR_post_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") if (NOT WMOPS) - add_custom_command(TARGET ivas_lc3plus_unit_test POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/split_rendering/lc3plus") + add_custom_command(TARGET ivas_lc3plus_unit_test POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/split_rendering/lc3plus_float") endif() endif() diff --git a/scripts/split_rendering/lc3plus/.gitignore b/scripts/split_rendering/lc3plus_basop/.gitignore similarity index 100% rename from scripts/split_rendering/lc3plus/.gitignore rename to scripts/split_rendering/lc3plus_basop/.gitignore diff --git a/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test.c b/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test.c new file mode 100644 index 0000000000000000000000000000000000000000..d4617c13c2af27742de23d0d44e6c284ef7289d2 --- /dev/null +++ b/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test.c @@ -0,0 +1,875 @@ +/****************************************************************************************************** + +(C) 2022-2024 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. + +*******************************************************************************************************/ + +#include +#include +#include +#include "options.h" +#include "isar_lc3plus_enc.h" +#include "isar_lc3plus_common.h" +#include "isar_lc3plus_dec.h" +#include "ivas_error_utils.h" +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#include "lc3.h" +#endif + +#ifdef SPLIT_REND_WITH_HEAD_ROT +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#define MAX_SAMPLES_PER_CHANNEL 960 / 4 +#else +#define MAX_SAMPLES_PER_CHANNEL 960 +#endif +#define DEFAULT_BPS 256000 + +#ifndef PCM_SAMPLE_TYPEDEF_DEFINED +#define PCM_SAMPLE_TYPEDEF_DEFINED +typedef int32_t PcmSample; +#endif + +static int encodeAndDecodeOneStereoFrame( LC3PLUS_CONFIG config, uint32_t bps ) +{ + ivas_error err; + int32_t encDelay = -1; + int32_t decDelay = -1; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + err = ISAR_LC3PLUS_ENC_GetDelay( encHandle, &encDelay ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return err; + } + if ( encDelay == -1 || encDelay == 0 ) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "encDelay is zero or uninitialized\n" ); + } + + /* encode one frame */ + int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us ); + PcmSample *pcm_in[2]; + PcmSample pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + PcmSample pcm_in_ch2[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_in_ch2, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_in[0] = pcm_in_ch1; + pcm_in[1] = pcm_in_ch2; + + int32_t bitstreamSizePerIvasFrame = 0; + err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return err; + } + uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame ); + memset( bitstream_out, 0, bitstreamSizePerIvasFrame ); + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + int perChannelBitrate = lc3plus_enc_get_real_bitrate(encHandle->handles[0]); + int perLc3plusFrameDataBlockOctets = encHandle->num_ftds * perChannelBitrate / 8 / (1000*1000/config.lc3plus_frame_duration_us); + int targetOctets = bps / 8 / (1000*1000/config.isar_frame_duration_us); + printf("IVAS-FS=%i LC3plus-FS=%i ch=%i targetBps=%i targetOctets=%i\n", config.isar_frame_duration_us, config.lc3plus_frame_duration_us, config.channels, bps, targetOctets); + printf(" coreBps=%i corePerChBps=%i coreCodecOctets=%i nFtds=%i \n", perChannelBitrate * encHandle->num_encs, perChannelBitrate, perLc3plusFrameDataBlockOctets, encHandle->num_ftds); + int pfOctets = bitstreamSizePerIvasFrame - perLc3plusFrameDataBlockOctets; + int pfBps = pfOctets * 8 * (1000*1000 / config.isar_frame_duration_us); + printf(" payloadFormatBps=%i payloadFormatOctets=%i \n\n", pfBps, pfOctets); + if(pfBps <= 0) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return err; + } + + Word16 Q_in[16]; + memset(Q_in, 0, sizeof(Q_in) ); + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out, bitstreamSizePerIvasFrame, Q_in ); +#else + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out ); +#endif + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_ENC_Close( &encHandle ); + free( bitstream_out ); + return err; + } + ISAR_LC3PLUS_ENC_Close( &encHandle ); + + /* decode one frame */ + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + if ( IVAS_ERR_OK != err ) + { + free( bitstream_out ); + return err; + } + + err = ISAR_LC3PLUS_DEC_GetDelay( decHandle, &decDelay ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return err; + } + if ( decDelay == -1 || decDelay == 0 ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return IVAS_ERROR( IVAS_ERR_INTERNAL, "decDelay is zero or uninitialized\n" ); + } + + uint8_t *bitstream_in = bitstream_out; + + PcmSample *pcm_out[2]; + PcmSample pcm_out_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_out_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + PcmSample pcm_out_ch2[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_out_ch2, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_out[0] = pcm_out_ch1; + pcm_out[1] = pcm_out_ch2; + + err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return err; + } + + err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return err; + } + + err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + return err; + } + + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + + return 0; +} + + +static int openCloseEncoder( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + uint32_t bps = 128000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + ISAR_LC3PLUS_ENC_Close( &encHandle ); + return 0; +} + +static int tryOpenEncoderWithInvalidBitrate( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + /* lc3plus max bitrate is 320000 per channel */ + uint32_t invalid_high_bps = 700000; + uint32_t invalid_low_bps = 8; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + uint32_t limitedBitrate; +#endif + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, invalid_high_bps, &encHandle ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + /* setting an invalid bitrate should result in a limited bitrate*/ + if ( IVAS_ERR_OK != err ) +#else + /* setting an invalid bitrate should trigger an error - which is what we expect */ + if ( IVAS_ERR_LC3PLUS_INVALID_BITRATE != err ) +#endif + { + return 1; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + limitedBitrate = lc3plus_enc_get_real_bitrate(encHandle->handles[0]); + if(limitedBitrate != 320000) + { + return 1; + } +#endif + ISAR_LC3PLUS_ENC_Close(&encHandle); + err = ISAR_LC3PLUS_ENC_Open( config, invalid_low_bps, &encHandle ); + /* setting an invalid bitrate should trigger an error - which is what we expect */ + if ( IVAS_ERR_LC3PLUS_INVALID_BITRATE != err ) + { + return 1; + } + ISAR_LC3PLUS_ENC_Close(&encHandle); + return 0; +} + +static int tryOpenEncoderWithInvalidFrameDuration( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + config.lc3plus_frame_duration_us = 1234; /*unsupported frame duration*/ + uint32_t bps = 320000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + /* setting an invalid fame duration should trigger an error - which is what we expect */ + if ( IVAS_ERR_OK == err ) + { + return 1; + } + return 0; +} + +static int tryOpenEncoderWithInvalidSampleRate( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + config.samplerate = 1234; /*unsupported sample rate */ + uint32_t bps = 320000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + /* setting an invalid sample rate should trigger an error - which is what we expect */ + if ( IVAS_ERR_OK == err ) + { + return 1; + } + return 0; +} + +static int tryCallEncoderApiWithInvalidParams( void ) +{ + ISAR_LC3PLUS_ENC_HANDLE invalidEncHandle = NULL; + int32_t *invalidBsSize = NULL; + int32_t bsSize; + int32_t *invalidDelayInSamples = NULL; + int32_t delayInSamples; + PcmSample **invalidPcm_in = NULL; + void *invalidBitstream_out = NULL; + + const int16_t numSamplesPerChannels = MAX_SAMPLES_PER_CHANNEL; + PcmSample *pcm_in[1]; + PcmSample pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_in[0] = pcm_in_ch1; + uint8_t bitstream_out[1200]; + + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetDelay( invalidEncHandle, invalidDelayInSamples ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetDelay( invalidEncHandle, &delayInSamples ) ) + { + return 1; + } + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( invalidEncHandle, invalidBsSize ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( invalidEncHandle, &bsSize ) ) + { + return 1; + } + ISAR_LC3PLUS_ENC_Close( &invalidEncHandle ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 Q_in[16]; + memset(Q_in, 0, sizeof(Q_in) ); + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, invalidBitstream_out, bsSize, Q_in ) ) +#else + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, invalidBitstream_out ) ) +#endif + { + return 1; + } +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + memset(Q_in, 0, sizeof(Q_in) ); + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, invalidBitstream_out, bsSize, Q_in) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, bitstream_out, bsSize, Q_in ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, bitstream_out, bsSize, Q_in ) ) +#else + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, invalidBitstream_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, invalidPcm_in, bitstream_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_ENC_Encode( invalidEncHandle, pcm_in, bitstream_out ) ) +#endif + { + return 1; + } + return 0; +} + + +static int tryCallDecoderApiWithInvalidParams( void ) +{ + ISAR_LC3PLUS_DEC_HANDLE invalidDecHandle = NULL; + + int32_t *invalidDelayInSamples = NULL; + int32_t delayInSamples; + PcmSample **invalidPcm_out = NULL; + void *invalidBitstream_in = NULL; + int32_t invalidBitstream_in_size = 0; + int32_t bitstream_in_size = 100; + + const int16_t numSamplesPerChannels = MAX_SAMPLES_PER_CHANNEL; + PcmSample *pcm_out[1]; + PcmSample pcm_out_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_out_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_out[0] = pcm_out_ch1; + uint8_t bitstream_in[1200]; + + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_GetDelay( invalidDecHandle, invalidDelayInSamples ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_GetDelay( invalidDecHandle, &delayInSamples ) ) + { + return 1; + } + ISAR_LC3PLUS_DEC_Close( &invalidDecHandle ); + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, invalidBitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, invalidBitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, bitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, invalidBitstream_in, bitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, invalidBitstream_in_size, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, invalidBitstream_in_size, pcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Decode( invalidDecHandle, bitstream_in, bitstream_in_size, pcm_out ) ) + { + return 1; + } + + if ( IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Conceal( invalidDecHandle, invalidPcm_out ) || IVAS_ERR_UNEXPECTED_NULL_POINTER != ISAR_LC3PLUS_DEC_Conceal( invalidDecHandle, pcm_out ) ) + { + return 1; + } + return 0; +} + +static int openCloseDecoderWithCaching( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + ISAR_LC3PLUS_DEC_Close( &decHandle ); + return 0; +} + +static int openCloseDecoderWithoutCaching( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + ISAR_LC3PLUS_DEC_Close( &decHandle ); + return 0; +} + + +static int tryOpenDecoderWithInvalidFrameDuration( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + config.lc3plus_frame_duration_us = 1234; /*unsupported frame duration*/ + + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + /* setting an invalid fame duration should trigger an error - which is what we expect */ + if ( IVAS_ERR_OK == err ) + { + return 1; + } + return 0; +} + +static int tryOpenDecoderWithInvalidSampleRate( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + config.samplerate = 1234; /*unsupported sample rate*/ + + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + /* setting an invalid sample rate should trigger an error - which is what we expect */ + if ( IVAS_ERR_OK == err ) + { + return 1; + } + return 0; +} + +static int encodeOneFrame( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + uint32_t bps = 128000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + if ( IVAS_ERR_OK != err ) + return err; + + int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us ); + + PcmSample *pcm[1]; + PcmSample pcm_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm[0] = pcm_ch1; + + int32_t bitstreamSizePerIvasFrame = 0; + err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame ); + if ( IVAS_ERR_OK != err ) + return err; + uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame ); + memset( bitstream_out, 0, bitstreamSizePerIvasFrame ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 Q_in[16]; + memset(Q_in, 0, sizeof(Q_in) ); + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm, bitstream_out, bitstreamSizePerIvasFrame, Q_in ); + +#else + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm, bitstream_out ); +#endif + if ( IVAS_ERR_OK != err ) + return err; + + ISAR_LC3PLUS_ENC_Close( &encHandle ); + free( bitstream_out ); + return 0; +} + + +static int encodeAndDecodeOneMonoFrame( void ) +{ + ivas_error err; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20000, .channels = 1, .samplerate = 48000 }; +#endif + uint32_t bps = 128000; + + ISAR_LC3PLUS_ENC_HANDLE encHandle; + err = ISAR_LC3PLUS_ENC_Open( config, bps, &encHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + /* encode one frame */ + int16_t numSamplesPerChannels = config.samplerate / ( 1000000 / config.isar_frame_duration_us ); + PcmSample *pcm_in[1]; + PcmSample pcm_in_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_in_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_in[0] = pcm_in_ch1; + + int32_t bitstreamSizePerIvasFrame = 0; + err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( encHandle, &bitstreamSizePerIvasFrame ); + if ( IVAS_ERR_OK != err ) + return err; + + uint8_t *bitstream_out = malloc( bitstreamSizePerIvasFrame ); + memset( bitstream_out, 0, bitstreamSizePerIvasFrame ); +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + Word16 Q_in[16]; + memset(Q_in, 0, sizeof(Q_in) ); + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out, bitstreamSizePerIvasFrame, Q_in ); +#else + err = ISAR_LC3PLUS_ENC_Encode( encHandle, pcm_in, bitstream_out ); +#endif + if ( IVAS_ERR_OK != err ) + return err; + ISAR_LC3PLUS_ENC_Close( &encHandle ); + + /* decode one frame */ + ISAR_LC3PLUS_DEC_HANDLE decHandle; + err = ISAR_LC3PLUS_DEC_Open( config, +#ifdef LC3PLUS_DEC_ALLOW_DISABLE_CACHING + 1 /*caching enabled*/, +#endif + &decHandle ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + uint8_t *bitstream_in = bitstream_out; + + PcmSample *pcm_out[1]; + PcmSample pcm_out_ch1[MAX_SAMPLES_PER_CHANNEL * sizeof( PcmSample )]; + memset( pcm_out_ch1, 0, numSamplesPerChannels * sizeof( PcmSample ) ); + pcm_out[0] = pcm_out_ch1; + err = ISAR_LC3PLUS_DEC_Decode( decHandle, bitstream_in, bitstreamSizePerIvasFrame, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + err = ISAR_LC3PLUS_DEC_Conceal( decHandle, pcm_out ); + if ( IVAS_ERR_OK != err ) + { + return err; + } + + ISAR_LC3PLUS_DEC_Close( &decHandle ); + free( bitstream_out ); + + return 0; +} + +static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_32kHz( void ) +{ + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 32000 }; + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_16kHz( void ) +{ + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 16000 }; + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas5msLc3plus5ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3plus10ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneMonoFrameIvas20msLc3plus10ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 1, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneMonoFrameIvas5msLc3plus5ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 5 * 1000, .isar_frame_duration_us = 5 * 1000, .channels = 1, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + +static int encodeAndDecodeOneStereoFrameIvas20msLc3plus2_5ms_48kHz( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 2.5 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 2.5 * 1000, .isar_frame_duration_us = 20 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, DEFAULT_BPS ); +} + + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_80kbpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 82*1000 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_96kbpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 98*1000 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_124kbpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 126*1000 ); +} + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_800kbpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 800*1000 ); +} +#endif + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_204800bpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 204800 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_205600bpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 205600 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_206400bpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 206400 ); +} + +static int encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_207200bpsPerChannel( void ) +{ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 1, .samplerate = 48000, .high_res_mode_enabled = 0 }; +#else + LC3PLUS_CONFIG config = { .lc3plus_frame_duration_us = 10 * 1000, .isar_frame_duration_us = 10 * 1000, .channels = 2, .samplerate = 48000 }; +#endif + return encodeAndDecodeOneStereoFrame( config, config.channels * 207200 ); +} + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS +#include "ivas_lc3plus_unit_test_payload_format.c" +#endif + +int main( + int argc, + char *argv[] ) +{ + (void)argc; + (void)argv; + int ret = 0; + ret = openCloseEncoder(); + if ( ret != 0 ) + return 1; + ret = tryOpenEncoderWithInvalidBitrate(); + if ( ret != 0 ) + return 1; + ret = tryOpenEncoderWithInvalidFrameDuration(); + if ( ret != 0 ) + return 1; + ret = tryOpenEncoderWithInvalidSampleRate(); + if ( ret != 0 ) + return 1; + ret = tryCallEncoderApiWithInvalidParams(); + if ( ret != 0 ) + return 1; + ret = openCloseDecoderWithCaching(); + if ( ret != 0 ) + return 1; + ret = openCloseDecoderWithoutCaching(); + if ( ret != 0 ) + return 1; + ret = tryOpenDecoderWithInvalidFrameDuration(); + if ( ret != 0 ) + return 1; + ret = tryOpenDecoderWithInvalidSampleRate(); + if ( ret != 0 ) + return 1; + ret = tryCallDecoderApiWithInvalidParams(); + if ( ret != 0 ) + return 1; + ret = encodeOneFrame(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneMonoFrame(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_32kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus10ms_16kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas5msLc3plus5ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3plus10ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneMonoFrameIvas20msLc3plus10ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneMonoFrameIvas5msLc3plus5ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas20msLc3plus2_5ms_48kHz(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_80kbpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_96kbpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_124kbpsPerChannel(); + if ( ret != 0 ) + return 1; +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_800kbpsPerChannel(); + if ( ret != 0 ) + return 1; +#endif + /* start configs around the FDL threshold */ + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_204800bpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_205600bpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_206400bpsPerChannel(); + if ( ret != 0 ) + return 1; + ret = encodeAndDecodeOneStereoFrameIvas10msLc3_10ms_48kHz_207200bpsPerChannel(); + if ( ret != 0 ) + return 1; + /* end configs around the FDL threshold */ +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + ret = run_all_payload_tests(); + if ( ret != 0 ) + return 1; +#endif + return 0; +} +#else +int main( void ) +{ + return EXIT_SUCCESS; +} +#endif /* SPLIT_REND_WITH_HEAD_ROT */ diff --git a/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test_payload_format.c b/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test_payload_format.c new file mode 100644 index 0000000000000000000000000000000000000000..a303d01f53ee873fe70c0fbad2a9b6a540daa154 --- /dev/null +++ b/scripts/split_rendering/lc3plus_basop/ivas_lc3plus_unit_test_payload_format.c @@ -0,0 +1,451 @@ +/****************************************************************************************************** + +(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. + +*******************************************************************************************************/ + +#include +#include +#include +#include "isar_lc3plus_payload.h" +#include "ivas_error_utils.h" +#include "isar_lc3plus_common.h" +#include "options.h" + +#ifdef ISAR_BITSTREAM_UPDATE_LC3PLUS + +/* included by ivas_lc3plus_unit_test.c */ + +#define LC3PLUS_MAX_NUM_CODERS 16 +#define LC3PLUS_MAX_BS_SIZE LC3PLUS_MAX_NUM_CODERS *( 720 * LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES ) +#define SIZE_70 70 +#define SIZE_160 160 +#define SIZE_320 320 +#define SIZE_600 600 + +static int pack_and_unpack_payload_config_2ch_10ms_lc3plus_20ms_ivas( void ) +{ + LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS]; + int32_t sender_ftds_num = 0; + const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA; + + LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0]; + ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_01->frame_data = NULL; + ftd_L_01->frame_data_length = SIZE_160; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_01 = &sender_ftds[1]; + ftd_R_01->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + ftd_R_01->fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + ftd_R_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_01->frame_data = NULL; + ftd_R_01->frame_data_length = SIZE_600; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_L_02 = &sender_ftds[2]; + ftd_L_02->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_02->fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + ftd_L_02->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_02->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_02->frame_data = NULL; + ftd_L_02->frame_data_length = SIZE_320; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_02 = &sender_ftds[3]; + ftd_R_02->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + ftd_R_02->fdi = LC3PLUS_RTP_FTD_FDI_10000_US; + ftd_R_02->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_02->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_02->frame_data = NULL; + ftd_R_02->frame_data_length = SIZE_160; + sender_ftds_num++; + + const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE; + size_t packed_buffer_actual_size; + uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE]; + memset( packed_buffer, 0, packed_buffer_capacity ); + // prepare bitstream buffer headers & layout + LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } + + // copy encoded frames into their expected memory locations + uint8_t frame_data_L_01[SIZE_160]; + memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) ); + uint8_t frame_data_R_01[SIZE_600]; + memset( frame_data_R_01, 0x02, sizeof( frame_data_R_01 ) ); + uint8_t frame_data_L_02[SIZE_320]; + memset( frame_data_L_02, 0x03, sizeof( frame_data_L_02 ) ); + uint8_t frame_data_R_02[SIZE_160]; + memset( frame_data_R_02, 0x04, sizeof( frame_data_R_02 ) ); + memcpy( sender_ftds[0].frame_data, frame_data_L_01, sender_ftds[0].frame_data_length ); + memcpy( sender_ftds[1].frame_data, frame_data_R_01, sender_ftds[1].frame_data_length ); + memcpy( sender_ftds[2].frame_data, frame_data_L_02, sender_ftds[2].frame_data_length ); + memcpy( sender_ftds[3].frame_data, frame_data_R_02, sender_ftds[3].frame_data_length ); + + uint8_t *receiverBuffer = malloc( packed_buffer_actual_size ); + assert( NULL != receiverBuffer ); + memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size ); + + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + + assert( payload_config.fdl_request == fdl_req ); + assert( payload_config.frame_duration_us == 10000 ); + assert( payload_config.high_resolution_enabled == 0 ); + assert( payload_config.sampling_rate_hz == 48000 ); + assert( payload_config.num_ftds == 4 ); + assert( payload_config.num_media_times == 2 ); + assert( payload_config.num_channels == 2 ); + for ( int32_t i = 0; i < payload_config.num_ftds; ++i ) + { + assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length ); + assert( payload_config.ftds[i].h == sender_ftds[i].h ); + assert( payload_config.ftds[i].fdi == sender_ftds[i].fdi ); + assert( payload_config.ftds[i].bwr == sender_ftds[i].bwr ); + assert( payload_config.ftds[i].fc == sender_ftds[i].fc ); + assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length ); + assert( payload_config.ftds[i].frame_data != sender_ftds[i].frame_data ); + assert( 0 == memcmp( payload_config.ftds[i].frame_data, sender_ftds[i].frame_data, sender_ftds[i].frame_data_length ) ); + } + + free( receiverBuffer ); + return 0; +} + +static int pack_and_unpack_payload_config_2ch_5ms_lc3plus_20ms_ivas( void ) +{ + LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS]; + int32_t sender_ftds_num = 0; + const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA; + + LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0]; + ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_01->frame_data = NULL; + ftd_L_01->frame_data_length = SIZE_70; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_01 = &sender_ftds[1]; + ftd_R_01->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + ftd_R_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_R_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_01->frame_data = NULL; + ftd_R_01->frame_data_length = SIZE_320; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_L_02 = &sender_ftds[2]; + ftd_L_02->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_02->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_02->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_02->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_02->frame_data = NULL; + ftd_L_02->frame_data_length = SIZE_70; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_02 = &sender_ftds[3]; + ftd_R_02->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + ftd_R_02->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_R_02->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_02->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_02->frame_data = NULL; + ftd_R_02->frame_data_length = SIZE_160; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_L_03 = &sender_ftds[4]; + ftd_L_03->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_03->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_03->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_03->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_03->frame_data = NULL; + ftd_L_03->frame_data_length = SIZE_70; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_03 = &sender_ftds[5]; + ftd_R_03->fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME; + ftd_R_03->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_R_03->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_03->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_03->frame_data = NULL; + ftd_R_03->frame_data_length = SIZE_320; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_L_04 = &sender_ftds[6]; + ftd_L_04->fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL; + ftd_L_04->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_04->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_04->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_04->frame_data = NULL; + ftd_L_04->frame_data_length = SIZE_70; + sender_ftds_num++; + + LC3PLUS_RTP_FTD *ftd_R_04 = &sender_ftds[7]; + ftd_R_04->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + ftd_R_04->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_R_04->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_R_04->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_R_04->frame_data = NULL; + ftd_R_04->frame_data_length = SIZE_160; + sender_ftds_num++; + + const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE; + size_t packed_buffer_actual_size; + uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE]; + memset( packed_buffer, 0, packed_buffer_capacity ); + // prepare bitstream buffer headers & layout + LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } + + + // copy encoded frames into their expected memory locations + uint8_t frame_data_L_01[SIZE_70]; + assert( ftd_L_01->frame_data_length == sizeof( frame_data_L_01 ) ); + memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) ); + uint8_t frame_data_R_01[SIZE_320]; + assert( ftd_R_01->frame_data_length == sizeof( frame_data_R_01 ) ); + memset( frame_data_R_01, 0x02, sizeof( frame_data_R_01 ) ); + uint8_t frame_data_L_02[SIZE_70]; + assert( ftd_L_02->frame_data_length == sizeof( frame_data_L_02 ) ); + memset( frame_data_L_02, 0x03, sizeof( frame_data_L_02 ) ); + uint8_t frame_data_R_02[SIZE_160]; + assert( ftd_R_02->frame_data_length == sizeof( frame_data_R_02 ) ); + memset( frame_data_R_02, 0x04, sizeof( frame_data_R_02 ) ); + uint8_t frame_data_L_03[SIZE_70]; + assert( ftd_L_03->frame_data_length == sizeof( frame_data_L_03 ) ); + memset( frame_data_L_03, 0x05, sizeof( frame_data_L_03 ) ); + uint8_t frame_data_R_03[SIZE_320]; + assert( ftd_R_03->frame_data_length == sizeof( frame_data_R_03 ) ); + memset( frame_data_R_03, 0x06, sizeof( frame_data_R_03 ) ); + uint8_t frame_data_L_04[SIZE_70]; + assert( ftd_L_04->frame_data_length == sizeof( frame_data_L_04 ) ); + memset( frame_data_L_04, 0x07, sizeof( frame_data_L_04 ) ); + uint8_t frame_data_R_04[SIZE_160]; + assert( ftd_R_04->frame_data_length == sizeof( frame_data_R_04 ) ); + memset( frame_data_R_04, 0x08, sizeof( frame_data_R_04 ) ); + memcpy( sender_ftds[0].frame_data, frame_data_L_01, sender_ftds[0].frame_data_length ); + memcpy( sender_ftds[1].frame_data, frame_data_R_01, sender_ftds[1].frame_data_length ); + memcpy( sender_ftds[2].frame_data, frame_data_L_02, sender_ftds[2].frame_data_length ); + memcpy( sender_ftds[3].frame_data, frame_data_R_02, sender_ftds[3].frame_data_length ); + memcpy( sender_ftds[4].frame_data, frame_data_L_03, sender_ftds[4].frame_data_length ); + memcpy( sender_ftds[5].frame_data, frame_data_R_03, sender_ftds[5].frame_data_length ); + memcpy( sender_ftds[6].frame_data, frame_data_L_04, sender_ftds[6].frame_data_length ); + memcpy( sender_ftds[7].frame_data, frame_data_R_04, sender_ftds[7].frame_data_length ); + + uint8_t *receiverBuffer = malloc( packed_buffer_actual_size ); + assert( NULL != receiverBuffer ); + memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size ); + + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + + assert( payload_config.fdl_request == fdl_req ); + assert( payload_config.frame_duration_us == 5000 ); + assert( payload_config.high_resolution_enabled == 0 ); + assert( payload_config.sampling_rate_hz == 48000 ); + assert( payload_config.num_ftds == 8 ); + assert( payload_config.num_media_times == 4 ); + assert( payload_config.num_channels == 2 ); + for ( int32_t i = 0; i < payload_config.num_ftds; ++i ) + { + assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length ); + assert( payload_config.ftds[i].h == sender_ftds[i].h ); + assert( payload_config.ftds[i].fdi == sender_ftds[i].fdi ); + assert( payload_config.ftds[i].bwr == sender_ftds[i].bwr ); + assert( payload_config.ftds[i].fc == sender_ftds[i].fc ); + assert( payload_config.ftds[i].frame_data_length == sender_ftds[i].frame_data_length ); + assert( payload_config.ftds[i].frame_data != sender_ftds[i].frame_data ); + assert( 0 == memcmp( payload_config.ftds[i].frame_data, sender_ftds[i].frame_data, sender_ftds[i].frame_data_length ) ); + } + + free( receiverBuffer ); + return 0; +} + +static int try_unpack_invalid_values( void ) +{ + LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS]; + int32_t sender_ftds_num = 0; + const LC3PLUS_RTP_FDL fdl_req = LC3PLUS_RTP_FDL_LENGTH_3_MAX; + + LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0]; + ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_01->frame_data = NULL; + ftd_L_01->frame_data_length = SIZE_70; + sender_ftds_num++; + + const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE; + size_t packed_buffer_actual_size; + uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE]; + memset( packed_buffer, 0, packed_buffer_capacity ); + // prepare bitstream buffer headers & layout + LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_req, sender_ftds, sender_ftds_num ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } + + // copy encoded frames into their expected memory locations + uint8_t frame_data_L_01[SIZE_70]; + assert( ftd_L_01->frame_data_length == sizeof( frame_data_L_01 ) ); + memset( frame_data_L_01, 0x01, sizeof( frame_data_L_01 ) ); + + uint8_t *receiverBuffer = malloc( packed_buffer_actual_size ); + assert( NULL != receiverBuffer ); + memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size ); + + int32_t fdl_req_length; + error = LC3PLUS_RTP_frame_data_length_get_size( &fdl_req_length, fdl_req ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_frame_data_length_get_size error\n" ); + } + for ( int16_t packed_buffer_incorrect_size = 0; packed_buffer_incorrect_size < ( fdl_req_length + 2 + SIZE_70 ); ++packed_buffer_incorrect_size ) + { + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_incorrect_size ); + if ( error == LC3PLUS_RTP_ERR_NO_ERROR ) + { + free( receiverBuffer ); + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed to detect error\n" ); + } + } + + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + free( receiverBuffer ); + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + free( receiverBuffer ); + return 0; +} + +#define LC3PLUS_RTP_TEST_NUM_FTDS_UT 3 +static int pack_and_unpack_different_fdl_sizes( void ) +{ + int32_t iFtdUt; + LC3PLUS_RTP_FDL fdl_requests_ut[LC3PLUS_RTP_TEST_NUM_FTDS_UT]; + fdl_requests_ut[0] = LC3PLUS_RTP_FDL_LENGTH_1_MIN; + fdl_requests_ut[1] = LC3PLUS_RTP_FDL_LENGTH_2_MIN; + fdl_requests_ut[2] = LC3PLUS_RTP_FDL_LENGTH_3_MIN; + + for ( iFtdUt = 0; iFtdUt < LC3PLUS_RTP_TEST_NUM_FTDS_UT; ++iFtdUt ) + { + LC3PLUS_RTP_FTD sender_ftds[LC3PLUS_MAX_NUM_CODERS]; + int32_t sender_ftds_num = 0; + + LC3PLUS_RTP_FTD *ftd_L_01 = &sender_ftds[0]; + ftd_L_01->fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL; + ftd_L_01->fdi = LC3PLUS_RTP_FTD_FDI_5000_US; + ftd_L_01->bwr = LC3PLUS_RTP_FTD_BWR_FB; + ftd_L_01->h = LC3PLUS_RTP_FTD_H_PRIMARY; + ftd_L_01->frame_data = NULL; + ftd_L_01->frame_data_length = fdl_requests_ut[iFtdUt]; + sender_ftds_num++; + + const size_t packed_buffer_capacity = LC3PLUS_MAX_BS_SIZE; + size_t packed_buffer_actual_size; + uint8_t packed_buffer[LC3PLUS_MAX_BS_SIZE]; + memset( packed_buffer, 0, packed_buffer_capacity ); + // prepare bitstream buffer headers & layout + LC3PLUS_RTP_ERR error = LC3PLUS_RTP_payload_serialize( packed_buffer, packed_buffer_capacity, &packed_buffer_actual_size, fdl_requests_ut[iFtdUt], sender_ftds, sender_ftds_num ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_serialize failed\n" ); + } + + // copy encoded frames into their expected memory locations + uint8_t frame_data_L_01[SIZE_600]; + assert( ftd_L_01->frame_data_length <= sizeof( frame_data_L_01 ) ); + memset( frame_data_L_01, 0x01, ftd_L_01->frame_data_length ); + + uint8_t *receiverBuffer = malloc( packed_buffer_actual_size ); + assert( NULL != receiverBuffer ); + memcpy( receiverBuffer, packed_buffer, packed_buffer_actual_size ); + + LC3PLUS_RTP_PAYLOAD payload_config; + error = LC3PLUS_RTP_payload_deserialize( &payload_config, receiverBuffer, packed_buffer_actual_size ); + if ( error != LC3PLUS_RTP_ERR_NO_ERROR ) + { + free( receiverBuffer ); + return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( error ), "LC3PLUS_RTP_payload_deserialize failed\n" ); + } + assert( payload_config.fdl_request == fdl_requests_ut[iFtdUt] ); + assert( payload_config.ftds[0].frame_data_length == fdl_requests_ut[iFtdUt] ); + free( receiverBuffer ); + } + return 0; +} + +static int run_all_payload_tests( void ) +{ + if ( pack_and_unpack_payload_config_2ch_10ms_lc3plus_20ms_ivas() != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" ); + } + if ( pack_and_unpack_payload_config_2ch_5ms_lc3plus_20ms_ivas() != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" ); + } + if ( try_unpack_invalid_values() != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" ); + } + if ( pack_and_unpack_different_fdl_sizes() != 0 ) + { + return IVAS_ERROR( IVAS_ERR_INTERNAL, "test failed\n" ); + } + return 0; +} +#endif diff --git a/scripts/split_rendering/lc3plus_basop/split_rend_lc3plus_cmdlines.py b/scripts/split_rendering/lc3plus_basop/split_rend_lc3plus_cmdlines.py new file mode 100644 index 0000000000000000000000000000000000000000..033c25bb6027ab2752bf58c33ec9b70cdff50650 --- /dev/null +++ b/scripts/split_rendering/lc3plus_basop/split_rend_lc3plus_cmdlines.py @@ -0,0 +1,191 @@ +""" +Generate command lines for split rendering with LC3plus +""" + +import itertools +import os + +# Paths +ENC_PATH = "./IVAS_cod" +DEC_PATH = "./IVAS_dec" +REND_PATH = "./IVAS_rend" +TEMP_DIR = "tmp" + +# Config values to iterate over +ISM_CONFIGS_NUM_OBJECTS = [1, 2, 3, 4] +IVAS_BITRATES = [128000] +PRE_HEAD_ROT_FILES = [ + "Workspace_msvc/trajectories/pre-renderer_pose_files/pre_yaw-20static.csv" +] +POST_HEAD_ROT_FILES = [ + "Workspace_msvc/trajectories/post-renderer_pose_files/post_0static.csv" +] +RENDER_CONFIG_FILES = [ + ####################################################### + # Alternative 2 - LC3plus with CLDFB pose correction + "Workspace_msvc/renderer_configs/split_renderer_config_768_1dof.txt", + "Workspace_msvc/renderer_configs/split_renderer_config_512_2dof.txt", + None, # Alternative 2 is the default when no rendering config file is given on command line + ####################################################### + # Alternative 3 - LC3plus with multi-stream (TD) pose correction + "Workspace_msvc/renderer_configs/split_renderer_config_768_1dof_tdposecorr.txt", + "Workspace_msvc/renderer_configs/split_renderer_config_1536_2dof_tdposecorr.txt", +] + + +def audio_for_ism(num_objects): + return f"scripts/testv/stv{num_objects}ISM48s.wav" + + +def metadata_for_ism(num_objects): + return f"scripts/testv/stvISM{num_objects}.csv" + + +def basename(file_path): + basename_w_ext = os.path.basename(file_path) + return os.path.splitext(basename_w_ext)[0] + + +# Full chain: IVAS_cod -> IVAS_dec -> IVAS_rend(post) +def full_chain( + num_objects, ivas_bitrate, pre_head_rot_file, render_config_file, post_head_rot_file +): + bs_name = f"{TEMP_DIR}/ism{num_objects}_b{ivas_bitrate}_full_chain.g192" + cod = [ + ENC_PATH, + "-ism", + str(num_objects), + *[metadata_for_ism(i + 1) for i in range(num_objects)], + str(ivas_bitrate), + "48", + audio_for_ism(num_objects), + bs_name, + ] + + render_config_infix = ( + f"##{basename(render_config_file)}" if render_config_file else "" + ) + split_bs_name = bs_name.replace( + ".g192", f"##{basename(pre_head_rot_file)}{render_config_infix}##split.bs" + ) + render_config_args = ( + ["-render_config", render_config_file] if render_config_file else [] + ) + dec = [ + DEC_PATH, + "-T", + pre_head_rot_file, + *render_config_args, + "SPLIT_BINAURAL", + "48", + bs_name, + split_bs_name, + ] + + binaural_output_name = split_bs_name.replace( + ".bs", f"##{basename(post_head_rot_file)}##binaural.wav" + ) + rend = [ + REND_PATH, + "-i", + split_bs_name, + "-if", + "BINAURAL_SPLIT_CODED", + "-of", + "BINAURAL", + "-fs", + "48", + "-tf", + post_head_rot_file, + "-o", + binaural_output_name, + ] + + return [cod, dec, rend] + + +# Renderer chain: IVAS_rend(pre) -> IVAS_rend(post) +def rend_chain(num_objects, pre_head_rot_file, render_config_file, post_head_rot_file): + render_config_infix = ( + f"##{basename(render_config_file)}" if render_config_file else "" + ) + split_bs_name = f"{TEMP_DIR}/ism{num_objects}_rend_chain##{basename(pre_head_rot_file)}{render_config_infix}##split.bs" + render_config_args = ( + ["-render_config", render_config_file] if render_config_file else [] + ) + pre = [ + REND_PATH, + "-i", + audio_for_ism(num_objects), + "-if", + f"ISM{num_objects}", + "-im", + *[metadata_for_ism(i + 1) for i in range(num_objects)], + "-of", + "BINAURAL_SPLIT_CODED", + "-fs", + "48", + *render_config_args, + "-tf", + pre_head_rot_file, + "-o", + split_bs_name, + ] + + binaural_output_name = split_bs_name.replace( + ".bs", f"##{basename(post_head_rot_file)}##binaural.wav" + ) + post = [ + REND_PATH, + "-i", + split_bs_name, + "-if", + "BINAURAL_SPLIT_CODED", + "-of", + "BINAURAL", + "-fs", + "48", + "-tf", + post_head_rot_file, + "-o", + binaural_output_name, + ] + + return [pre, post] + + +def print_command_list(list_of_lists): + for lst in list_of_lists: + print(" ".join(lst)) + print("") # newline + + +def main(): + print("\n##########################################") + print("# Full chain: enc -> dec -> rend(post)") + print("##########################################\n") + for args_full_chain in itertools.product( + # Ordering here must match argument order in function call below! + ISM_CONFIGS_NUM_OBJECTS, + IVAS_BITRATES, + PRE_HEAD_ROT_FILES, + RENDER_CONFIG_FILES, + POST_HEAD_ROT_FILES, + ): + print_command_list(full_chain(*args_full_chain)) + + print("\n##########################################") + print("# Renderer chain: rend(pre) -> rend(post)") + print("##########################################\n") + for args_rend_chain in itertools.product( + # Ordering here must match argument order in function call below! + ISM_CONFIGS_NUM_OBJECTS, + PRE_HEAD_ROT_FILES, + RENDER_CONFIG_FILES, + POST_HEAD_ROT_FILES, + ): + print_command_list(rend_chain(*args_rend_chain)) + + +if __name__ == "__main__": + main() diff --git a/scripts/split_rendering/lc3plus_float/.gitignore b/scripts/split_rendering/lc3plus_float/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..9cd2def1f8d1ce4f0300a90324e6479906a6f5cb --- /dev/null +++ b/scripts/split_rendering/lc3plus_float/.gitignore @@ -0,0 +1 @@ +ivas_lc3plus_unit_test \ No newline at end of file diff --git a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c b/scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test.c similarity index 100% rename from scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c rename to scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test.c diff --git a/scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_payload_format.c b/scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test_payload_format.c similarity index 100% rename from scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test_payload_format.c rename to scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test_payload_format.c