LCOV - code coverage report
Current view: top level - lib_isar - isar_lc3plus_payload.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 419 0.0 %
Date: 2025-08-23 01:22:27 Functions: 0 15 0.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdbool.h>
      34             : #include <assert.h>
      35             : #include <string.h>
      36             : #include "isar_lc3plus_payload.h"
      37             : #include "options.h"
      38             : 
      39           0 : static LC3PLUS_RTP_ERR s_frame_duration_ms_from_fdi( int32_t *frame_duration_us, const LC3PLUS_RTP_FTD_FDI fdi )
      40             : {
      41           0 :     if ( NULL == frame_duration_us )
      42             :     {
      43           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
      44             :     }
      45           0 :     switch ( fdi )
      46             :     {
      47           0 :         case LC3PLUS_RTP_FTD_FDI_2500_US:
      48           0 :             *frame_duration_us = 2500;
      49           0 :             break;
      50           0 :         case LC3PLUS_RTP_FTD_FDI_5000_US:
      51           0 :             *frame_duration_us = 5000;
      52           0 :             break;
      53           0 :         case LC3PLUS_RTP_FTD_FDI_10000_US:
      54           0 :             *frame_duration_us = 10000;
      55           0 :             break;
      56           0 :         case LC3PLUS_RTP_FTD_FDI_RESERVED:
      57             :         default:
      58           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
      59             :     }
      60           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
      61             : }
      62             : 
      63           0 : static LC3PLUS_RTP_ERR s_sampling_rate_hz_from_bwr( int32_t *sample_rate_hz, const LC3PLUS_RTP_FTD_BWR bwr )
      64             : {
      65           0 :     if ( NULL == sample_rate_hz )
      66             :     {
      67           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
      68             :     }
      69           0 :     switch ( bwr )
      70             :     {
      71           0 :         case LC3PLUS_RTP_FTD_BWR_NB:
      72           0 :             *sample_rate_hz = 8000;
      73           0 :             break;
      74           0 :         case LC3PLUS_RTP_FTD_BWR_WB:
      75           0 :             *sample_rate_hz = 16000;
      76           0 :             break;
      77           0 :         case LC3PLUS_RTP_FTD_BWR_SSWB:
      78           0 :             *sample_rate_hz = 24000;
      79           0 :             break;
      80           0 :         case LC3PLUS_RTP_FTD_BWR_SWB:
      81           0 :             *sample_rate_hz = 32000;
      82           0 :             break;
      83           0 :         case LC3PLUS_RTP_FTD_BWR_FBCD:
      84           0 :             *sample_rate_hz = 44100;
      85           0 :             break;
      86           0 :         case LC3PLUS_RTP_FTD_BWR_FB:
      87           0 :             *sample_rate_hz = 48000;
      88           0 :             break;
      89           0 :         case LC3PLUS_RTP_FTD_BWR_FBHR:
      90           0 :             *sample_rate_hz = 48000;
      91           0 :             break;
      92           0 :         case LC3PLUS_RTP_FTD_BWR_UBHR:
      93           0 :             *sample_rate_hz = 96000;
      94           0 :             break;
      95           0 :         default:
      96           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
      97             :     }
      98           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
      99             : }
     100             : 
     101           0 : static LC3PLUS_RTP_ERR s_high_resolution_flag_from_bwr( int16_t *high_resolution_flag, const LC3PLUS_RTP_FTD_BWR bwr )
     102             : {
     103           0 :     if ( NULL == high_resolution_flag )
     104             :     {
     105           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     106             :     }
     107           0 :     switch ( bwr )
     108             :     {
     109           0 :         case LC3PLUS_RTP_FTD_BWR_NB:
     110           0 :             *high_resolution_flag = 0;
     111           0 :             break;
     112           0 :         case LC3PLUS_RTP_FTD_BWR_WB:
     113           0 :             *high_resolution_flag = 0;
     114           0 :             break;
     115           0 :         case LC3PLUS_RTP_FTD_BWR_SSWB:
     116           0 :             *high_resolution_flag = 0;
     117           0 :             break;
     118           0 :         case LC3PLUS_RTP_FTD_BWR_SWB:
     119           0 :             *high_resolution_flag = 0;
     120           0 :             break;
     121           0 :         case LC3PLUS_RTP_FTD_BWR_FBCD:
     122           0 :             *high_resolution_flag = 0;
     123           0 :             break;
     124           0 :         case LC3PLUS_RTP_FTD_BWR_FB:
     125           0 :             *high_resolution_flag = 0;
     126           0 :             break;
     127           0 :         case LC3PLUS_RTP_FTD_BWR_FBHR:
     128           0 :             *high_resolution_flag = 1;
     129           0 :             break;
     130           0 :         case LC3PLUS_RTP_FTD_BWR_UBHR:
     131           0 :             *high_resolution_flag = 1;
     132           0 :             break;
     133           0 :         default:
     134           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     135             :     }
     136           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     137             : }
     138             : 
     139           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size( int32_t *length, const LC3PLUS_RTP_FDL frameDataLengthValue )
     140             : {
     141           0 :     if ( frameDataLengthValue == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_BAD || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_SID )
     142             :     {
     143           0 :         *length = 1;
     144             :     }
     145           0 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_1_MAX )
     146             :     {
     147           0 :         *length = 1;
     148             :     }
     149           0 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_2_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_2_MAX )
     150             :     {
     151           0 :         *length = 2;
     152             :     }
     153           0 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_3_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
     154             :     {
     155           0 :         *length = 3;
     156             :     }
     157             :     else
     158             :     {
     159           0 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     160             :     }
     161           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     162             : }
     163             : 
     164           0 : static LC3PLUS_RTP_ERR s_frame_data_length_pack( const LC3PLUS_RTP_FDL frameDataLengthValue, uint8_t *dst )
     165             : {
     166             :     int32_t frame_data_length_size;
     167             :     LC3PLUS_RTP_ERR err;
     168             : 
     169           0 :     if ( NULL == dst )
     170             :     {
     171           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     172             :     }
     173             : 
     174           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, frameDataLengthValue );
     175           0 :     if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
     176             :     {
     177           0 :         return err;
     178             :     }
     179           0 :     if ( 1 == frame_data_length_size )
     180             :     {
     181           0 :         *dst++ = frameDataLengthValue >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     182             :     }
     183           0 :     else if ( 2 == frame_data_length_size )
     184             :     {
     185           0 :         const int32_t frameDataLengthValueToWrite = frameDataLengthValue - LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     186           0 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     187           0 :         *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     188             :     }
     189           0 :     else if ( 3 == frame_data_length_size )
     190             :     {
     191           0 :         const int32_t frameDataLengthValueToWrite = frameDataLengthValue - ( 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE );
     192           0 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     193           0 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     194           0 :         *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     195             :     }
     196           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     197             : }
     198             : 
     199           0 : static int32_t s_get_size_from_fdl( const LC3PLUS_RTP_FDL fdl )
     200             : {
     201           0 :     if ( fdl >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
     202             :     {
     203           0 :         return fdl;
     204             :     }
     205           0 :     return 0;
     206             : }
     207             : 
     208           0 : static bool s_fdl_is_magic_value( const LC3PLUS_RTP_FDL fdl )
     209             : {
     210           0 :     if ( fdl == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || fdl == LC3PLUS_RTP_FDL_SPEECH_SID || fdl == LC3PLUS_RTP_FDL_SPEECH_BAD )
     211             :     {
     212           0 :         return true;
     213             :     }
     214           0 :     return false;
     215             : }
     216             : 
     217           0 : static bool s_fdl_value_is_valid_request( const LC3PLUS_RTP_FDL fdl_request )
     218             : {
     219             :     /* LC3PLUS_RTP_FDL_SPEECH_SID && LC3PLUS_RTP_FDL_SPEECH_SID are not valid values for the FDL request */
     220           0 :     if ( fdl_request == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || ( fdl_request >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl_request <= LC3PLUS_RTP_FDL_LENGTH_3_MAX ) )
     221             :     {
     222           0 :         return true;
     223             :     }
     224           0 :     return false;
     225             : }
     226             : 
     227           0 : static LC3PLUS_RTP_ERR s_frame_data_length_parse( LC3PLUS_RTP_FDL *frame_data_length_value, const uint8_t *src, const size_t remaining_capacity )
     228             : {
     229             :     int32_t frame_data_length_size;
     230             :     LC3PLUS_RTP_ERR err;
     231           0 :     if ( NULL == src || NULL == frame_data_length_value || remaining_capacity < 1 )
     232             :     {
     233           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     234             :     }
     235             : 
     236           0 :     if ( remaining_capacity > 2 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *( src + 1 ) )
     237             :     {
     238           0 :         *frame_data_length_value = *( src + 2 ) + 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     239             :     }
     240           0 :     else if ( remaining_capacity > 1 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src )
     241             :     {
     242           0 :         *frame_data_length_value = *( src + 1 ) + 1 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     243             :     }
     244           0 :     else if ( remaining_capacity > 0 )
     245             :     {
     246           0 :         *frame_data_length_value = *src << 0;
     247             :     }
     248             :     else
     249             :     {
     250           0 :         return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     251             :     }
     252             : 
     253             :     /* sanity check */
     254           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, *frame_data_length_value );
     255           0 :     if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
     256             :     {
     257           0 :         return err;
     258             :     }
     259           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     260             : }
     261             : 
     262           0 : static LC3PLUS_RTP_ERR s_parse_ftd( const uint8_t *p_read, LC3PLUS_RTP_FTD *receiver_ftd, int32_t *num_bytes_read, const size_t remaining_capacity )
     263             : {
     264             :     int32_t frame_data_block_size;
     265             :     LC3PLUS_RTP_FDL fdl;
     266             :     LC3PLUS_RTP_ERR err;
     267           0 :     if ( NULL == p_read || NULL == receiver_ftd || NULL == num_bytes_read || remaining_capacity < LC3PLUS_RTP_FTD_MIN_SIZE )
     268             :     {
     269           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     270             :     }
     271             : 
     272           0 :     *num_bytes_read = 0;
     273           0 :     receiver_ftd->fc = 0;
     274           0 :     receiver_ftd->fdi = 0;
     275           0 :     receiver_ftd->bwr = 0;
     276           0 :     receiver_ftd->h = 0;
     277           0 :     receiver_ftd->fc |= *p_read & LC3PLUS_RTP_FTD_FC_MASK;
     278           0 :     receiver_ftd->fdi |= ( *p_read & LC3PLUS_RTP_FTD_FDI_MASK );
     279           0 :     receiver_ftd->bwr |= ( *p_read & LC3PLUS_RTP_FTD_BWR_MASK );
     280           0 :     receiver_ftd->h |= ( *p_read & LC3PLUS_RTP_FTD_H_MASK );
     281           0 :     p_read++;
     282           0 :     *num_bytes_read = 1;
     283             : 
     284           0 :     err = s_frame_data_length_parse( &fdl, p_read, remaining_capacity - *num_bytes_read );
     285           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     286             :     {
     287           0 :         return err;
     288             :     }
     289           0 :     frame_data_block_size = s_get_size_from_fdl( fdl );
     290             : 
     291           0 :     receiver_ftd->frame_data_length = frame_data_block_size;
     292             :     int32_t length_field_size;
     293           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &length_field_size, receiver_ftd->frame_data_length );
     294           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     295             :     {
     296           0 :         return err;
     297             :     }
     298           0 :     *num_bytes_read += length_field_size;
     299           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     300             : }
     301             : 
     302           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_serialize(
     303             :     uint8_t *serialized_buffer,
     304             :     const size_t serialized_buffer_capacity,
     305             :     size_t *packed_buffer_actual_size,
     306             :     const LC3PLUS_RTP_FDL fdl_request,
     307             :     LC3PLUS_RTP_FTD *sender_ftds,
     308             :     const size_t sender_ftds_num )
     309             : {
     310             :     LC3PLUS_RTP_ERR err;
     311           0 :     uint8_t *p_write = serialized_buffer;
     312             :     uint32_t i;
     313           0 :     int32_t bytes_written = 0;
     314             :     int32_t lc3plus_frame_size_sum;
     315             :     uint8_t *p_frame_data;
     316             :     int32_t fdl_request_length;
     317             : 
     318           0 :     if ( NULL == serialized_buffer || NULL == packed_buffer_actual_size || NULL == sender_ftds )
     319             :     {
     320           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     321             :     }
     322             : 
     323           0 :     *packed_buffer_actual_size = 0;
     324           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, fdl_request );
     325           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     326             :     {
     327           0 :         return err;
     328             :     }
     329           0 :     if ( !s_fdl_value_is_valid_request( fdl_request ) )
     330             :     {
     331           0 :         return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
     332             :     }
     333           0 :     if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_request_length )
     334             :     {
     335           0 :         return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     336             :     }
     337           0 :     err = s_frame_data_length_pack( fdl_request, p_write );
     338           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     339             :     {
     340           0 :         return err;
     341             :     }
     342           0 :     bytes_written += fdl_request_length;
     343           0 :     p_write += bytes_written;
     344             : 
     345           0 :     for ( i = 0; i < sender_ftds_num; ++i )
     346             :     {
     347             :         /* only the last ftd may have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */
     348           0 :         if ( sender_ftds[i].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i != ( sender_ftds_num - 1 ) )
     349             :         {
     350           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     351             :         }
     352             :         /* the last ftd must have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */
     353           0 :         if ( sender_ftds[i].fc != LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i == ( sender_ftds_num - 1 ) )
     354             :         {
     355           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     356             :         }
     357           0 :         if ( (int32_t) serialized_buffer_capacity < bytes_written + LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL )
     358             :         {
     359           0 :             return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     360             :         }
     361           0 :         *p_write = 0x00;
     362           0 :         *p_write |= LC3PLUS_RTP_FTD_FC_MASK & (uint8_t) sender_ftds[i].fc;
     363           0 :         *p_write |= LC3PLUS_RTP_FTD_FDI_MASK & (uint8_t) sender_ftds[i].fdi;
     364           0 :         *p_write |= LC3PLUS_RTP_FTD_BWR_MASK & (uint8_t) sender_ftds[i].bwr;
     365           0 :         *p_write |= LC3PLUS_RTP_FTD_H_MASK & (uint8_t) sender_ftds[i].h;
     366           0 :         p_write++;
     367           0 :         bytes_written += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
     368             : 
     369             :         int32_t fdl_length;
     370           0 :         err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_length, sender_ftds[i].frame_data_length );
     371           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     372             :         {
     373           0 :             return err;
     374             :         }
     375           0 :         if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_length )
     376             :         {
     377           0 :             return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     378             :         }
     379           0 :         err = s_frame_data_length_pack( sender_ftds[i].frame_data_length, p_write );
     380           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     381             :         {
     382           0 :             return err;
     383             :         }
     384           0 :         p_write += fdl_length;
     385           0 :         bytes_written += fdl_length;
     386             :     }
     387             : 
     388           0 :     lc3plus_frame_size_sum = 0;
     389           0 :     p_frame_data = serialized_buffer + bytes_written;
     390           0 :     for ( i = 0; i < sender_ftds_num; ++i )
     391             :     {
     392           0 :         sender_ftds[i].frame_data = p_frame_data;
     393           0 :         p_frame_data += sender_ftds[i].frame_data_length;
     394           0 :         lc3plus_frame_size_sum += sender_ftds[i].frame_data_length;
     395             :     }
     396           0 :     *packed_buffer_actual_size = bytes_written + lc3plus_frame_size_sum;
     397           0 :     assert( *packed_buffer_actual_size <= serialized_buffer_capacity );
     398           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     399             : }
     400             : 
     401           0 : static LC3PLUS_RTP_ERR s_ftds_parse(
     402             :     LC3PLUS_RTP_FTD *receiver_ftds,
     403             :     const int32_t receiver_ftds_num_max,
     404             :     int16_t *receiver_ftds_num,
     405             :     uint8_t *serialized_buffer,
     406             :     const size_t serialized_buffer_size )
     407             : {
     408             :     int32_t diff;
     409             :     uint8_t *p_read;
     410           0 :     uint32_t ftds_offset_sum = 0;
     411             :     int16_t i;
     412             :     LC3PLUS_RTP_ERR error;
     413             :     int32_t frame_offset_counter;
     414             :     int32_t size;
     415             : 
     416           0 :     p_read = serialized_buffer;
     417           0 :     if ( NULL == receiver_ftds || NULL == receiver_ftds_num || NULL == serialized_buffer )
     418             :     {
     419           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     420             :     }
     421           0 :     if ( 0 == serialized_buffer_size )
     422             :     {
     423           0 :         return LC3PLUS_RTP_ERR_EMPTY_TOC;
     424             :     }
     425           0 :     if ( receiver_ftds_num_max <= 0 )
     426             :     {
     427           0 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     428             :     }
     429             :     {
     430           0 :         int32_t num_bytes_read_sum = 0;
     431           0 :         const int32_t min_num_bytes_per_ftd = 2;
     432           0 :         int16_t receiver_ftds_index = 0;
     433           0 :         bool another_ftd = true;
     434             :         int32_t num_bytes_read_per_ftd;
     435             : 
     436           0 :         while ( another_ftd )
     437             :         {
     438           0 :             if ( (int32_t) serialized_buffer_size < min_num_bytes_per_ftd )
     439             :             {
     440           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     441             :             }
     442           0 :             if ( num_bytes_read_sum >= (int32_t) serialized_buffer_size - min_num_bytes_per_ftd )
     443             :             {
     444           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     445             :             }
     446           0 :             num_bytes_read_per_ftd = 0;
     447           0 :             error = s_parse_ftd( p_read, &receiver_ftds[receiver_ftds_index], &num_bytes_read_per_ftd, serialized_buffer_size - num_bytes_read_sum );
     448           0 :             if ( LC3PLUS_RTP_ERR_NO_ERROR != error )
     449             :             {
     450           0 :                 return error;
     451             :             }
     452           0 :             p_read += num_bytes_read_per_ftd;
     453           0 :             num_bytes_read_sum += num_bytes_read_per_ftd;
     454             : 
     455           0 :             if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_RESERVED )
     456             :             {
     457           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
     458             :             }
     459           0 :             else if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL )
     460             :             {
     461           0 :                 another_ftd = false;
     462             :             }
     463             : 
     464           0 :             if ( another_ftd )
     465             :             {
     466           0 :                 if ( receiver_ftds_index >= receiver_ftds_num_max )
     467             :                 {
     468           0 :                     return LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED;
     469             :                 }
     470           0 :                 ( receiver_ftds_index )++;
     471             :             }
     472             :         }
     473           0 :         *receiver_ftds_num = receiver_ftds_index + 1;
     474             :     }
     475             : 
     476             :     /* set frame-data pointers into serialized_buffer */
     477           0 :     for ( i = 0; i < *receiver_ftds_num; ++i )
     478             :     {
     479           0 :         error = LC3PLUS_RTP_frame_data_length_get_size( &size, receiver_ftds[i].frame_data_length );
     480           0 :         if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
     481             :         {
     482           0 :             return error;
     483             :         }
     484           0 :         ftds_offset_sum += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + size;
     485             :     }
     486             : 
     487           0 :     frame_offset_counter = 0;
     488           0 :     for ( i = 0; i < *receiver_ftds_num; ++i )
     489             :     {
     490           0 :         if ( s_fdl_is_magic_value( receiver_ftds[i].frame_data_length ) )
     491             :         {
     492           0 :             receiver_ftds[i].frame_data = NULL;
     493             :         }
     494             :         else
     495             :         {
     496           0 :             receiver_ftds[i].frame_data = serialized_buffer + ftds_offset_sum + frame_offset_counter;
     497           0 :             frame_offset_counter += receiver_ftds[i].frame_data_length;
     498             :         }
     499             :     }
     500             : 
     501           0 :     if ( ftds_offset_sum + frame_offset_counter != serialized_buffer_size )
     502             :     {
     503             :         /* parsed content & size n bytes of input buffer do not line up */
     504             :         /* if the buffer capacity is larger and the remaining bytes are zero, we don't treat this as an error since it's due to the IVAS-Split rendering zero padding */
     505           0 :         diff = serialized_buffer_size - ( ftds_offset_sum + frame_offset_counter );
     506           0 :         if ( diff < 0 )
     507             :         {
     508           0 :             return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     509             :         }
     510             :         /* verify that all bytes are zero */
     511           0 :         p_read += frame_offset_counter;
     512           0 :         for ( i = 0; i < diff; ++i )
     513             :         {
     514           0 :             if ( *p_read != 0 )
     515             :             {
     516             :                 /* non-zero byte in padding region */
     517           0 :                 return LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES;
     518             :             }
     519           0 :             p_read++;
     520             :         }
     521             :     }
     522           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     523             : }
     524             : 
     525           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_deserialize(
     526             :     LC3PLUS_RTP_PAYLOAD *payload,
     527             :     uint8_t *serialized_buffer,
     528             :     const size_t serialized_buffer_size )
     529             : {
     530             :     int32_t new_frame_duration_us;
     531             :     int32_t new_sampling_rate_hz;
     532             :     int16_t new_high_resolution_flag;
     533           0 :     int16_t i = 0;
     534           0 :     int16_t channel_id = 0;
     535           0 :     int16_t media_time_id = 0;
     536           0 :     const int16_t invalid_value = -1;
     537             :     int16_t media_times_per_channel[LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS];
     538             :     int16_t channels_per_media_time[LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES];
     539             :     LC3PLUS_RTP_ERR err;
     540             : 
     541           0 :     if ( NULL == payload || NULL == serialized_buffer )
     542             :     {
     543           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     544             :     }
     545           0 :     if ( 0 == serialized_buffer_size )
     546             :     {
     547           0 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     548             :     }
     549             : 
     550           0 :     for ( media_time_id = 0; media_time_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++media_time_id )
     551             :     {
     552           0 :         channels_per_media_time[media_time_id] = invalid_value;
     553             :     }
     554           0 :     media_time_id = 0;
     555           0 :     for ( channel_id = 0; channel_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++channel_id )
     556             :     {
     557           0 :         media_times_per_channel[channel_id] = invalid_value;
     558             :     }
     559           0 :     channel_id = 0;
     560             : 
     561           0 :     err = s_frame_data_length_parse( &payload->fdl_request, serialized_buffer, serialized_buffer_size );
     562           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     563             :     {
     564           0 :         return err;
     565             :     }
     566             :     int32_t fdl_request_length;
     567           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, payload->fdl_request );
     568           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     569             :     {
     570           0 :         return err;
     571             :     }
     572           0 :     if ( !s_fdl_value_is_valid_request( payload->fdl_request ) )
     573             :     {
     574           0 :         return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
     575             :     }
     576             : 
     577           0 :     err = s_ftds_parse( payload->ftds, sizeof( payload->ftds ) / sizeof( LC3PLUS_RTP_FTD ), &payload->num_ftds, serialized_buffer + fdl_request_length, serialized_buffer_size - fdl_request_length );
     578           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     579             :     {
     580           0 :         return err;
     581             :     }
     582           0 :     if ( 0 == payload->num_ftds )
     583             :     {
     584           0 :         return LC3PLUS_RTP_ERR_GENERIC_ERROR;
     585             :     }
     586             :     /* verify shared setting between all FTDs [samplerate, frame_duration, channel count] */
     587             : 
     588             :     /* initialize on the first FTD, use this as reference */
     589           0 :     err = s_frame_duration_ms_from_fdi( &payload->frame_duration_us, payload->ftds[0].fdi );
     590           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     591             :     {
     592           0 :         return err;
     593             :     }
     594           0 :     err = s_sampling_rate_hz_from_bwr( &payload->sampling_rate_hz, payload->ftds[0].bwr );
     595           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     596             :     {
     597           0 :         return err;
     598             :     }
     599           0 :     err = s_high_resolution_flag_from_bwr( &payload->high_resolution_enabled, payload->ftds[0].bwr );
     600           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     601             :     {
     602           0 :         return err;
     603             :     }
     604           0 :     payload->num_channels = 0;
     605           0 :     payload->num_media_times = 0;
     606           0 :     for ( i = 0; i < payload->num_ftds; ++i )
     607             :     {
     608           0 :         if ( payload->ftds[i].h != LC3PLUS_RTP_FTD_H_PRIMARY )
     609             :         {
     610             :             /* not implemented */
     611           0 :             return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     612             :         }
     613             : 
     614           0 :         err = s_frame_duration_ms_from_fdi( &new_frame_duration_us, payload->ftds[i].fdi );
     615           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     616             :         {
     617           0 :             return err;
     618             :         }
     619           0 :         if ( payload->frame_duration_us != new_frame_duration_us )
     620             :         {
     621             :             /* mixed frame durations not supported */
     622           0 :             return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
     623             :         }
     624             : 
     625           0 :         err = s_sampling_rate_hz_from_bwr( &new_sampling_rate_hz, payload->ftds[i].bwr );
     626           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     627             :         {
     628           0 :             return err;
     629             :         }
     630           0 :         if ( payload->sampling_rate_hz != new_sampling_rate_hz )
     631             :         {
     632             :             /* mixed sampling frequencies not supported */
     633           0 :             return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
     634             :         }
     635             : 
     636             : 
     637           0 :         err = s_high_resolution_flag_from_bwr( &new_high_resolution_flag, payload->ftds[i].bwr );
     638           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     639             :         {
     640           0 :             return err;
     641             :         }
     642           0 :         if ( payload->high_resolution_enabled != new_high_resolution_flag )
     643             :         {
     644             :             /* mixed high resolution mode not supported */
     645           0 :             return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
     646             :         }
     647             : 
     648           0 :         switch ( payload->ftds[i].fc )
     649             :         {
     650           0 :             case LC3PLUS_RTP_FTD_FC_LAST_OVERALL:
     651           0 :                 channels_per_media_time[media_time_id]++;
     652           0 :                 media_times_per_channel[channel_id]++;
     653           0 :                 channel_id = 0;
     654           0 :                 media_time_id = 0;
     655           0 :                 break;
     656           0 :             case LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL:
     657           0 :                 media_times_per_channel[channel_id]++;
     658           0 :                 channels_per_media_time[media_time_id]++;
     659           0 :                 channel_id++;
     660           0 :                 break;
     661           0 :             case LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME:
     662           0 :                 media_times_per_channel[channel_id]++;
     663           0 :                 channels_per_media_time[media_time_id]++;
     664           0 :                 channel_id = 0;
     665           0 :                 media_time_id++;
     666           0 :                 break;
     667           0 :             case LC3PLUS_RTP_FTD_FC_RESERVED:
     668             :             default:
     669           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
     670             :         }
     671             :     }
     672             : 
     673             :     {
     674             :         int32_t valid_num_media_times_per_channel;
     675             :         int32_t iCh;
     676             :         /* check whether all channels exist for each media time */
     677           0 :         if ( media_times_per_channel[0] == invalid_value )
     678             :         {
     679           0 :             return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     680             :         }
     681           0 :         valid_num_media_times_per_channel = media_times_per_channel[0];
     682           0 :         for ( iCh = 0; iCh < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++iCh )
     683             :         {
     684           0 :             if ( media_times_per_channel[iCh] == invalid_value )
     685             :             {
     686           0 :                 break;
     687             :             }
     688           0 :             if ( valid_num_media_times_per_channel != media_times_per_channel[iCh] )
     689             :             {
     690           0 :                 return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     691             :             }
     692             :         }
     693             :     }
     694             :     {
     695             :         /*  whether all media times exist for each channel */
     696             :         int32_t iMediaTime;
     697             :         int32_t valid_num_channels_per_media_time;
     698           0 :         if ( channels_per_media_time[0] == invalid_value )
     699             :         {
     700           0 :             return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     701             :         }
     702           0 :         valid_num_channels_per_media_time = channels_per_media_time[0];
     703           0 :         for ( iMediaTime = 0; iMediaTime < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++iMediaTime )
     704             :         {
     705           0 :             if ( channels_per_media_time[iMediaTime] == invalid_value )
     706             :             {
     707           0 :                 break;
     708             :             }
     709           0 :             if ( valid_num_channels_per_media_time != channels_per_media_time[iMediaTime] )
     710             :             {
     711           0 :                 return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     712             :             }
     713             :         }
     714             :     }
     715             : 
     716             :     /* convert zero-index to count */
     717           0 :     payload->num_channels = channels_per_media_time[0] + 1;
     718           0 :     payload->num_media_times = media_times_per_channel[0] + 1;
     719             : 
     720             :     /* verify that all media times have the same number of channels, partial packets are not supported */
     721           0 :     if ( payload->num_ftds != payload->num_channels * payload->num_media_times )
     722             :     {
     723           0 :         return LC3PLUS_RTP_ERR_GENERIC_ERROR;
     724             :     }
     725           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     726             : }
     727             : 
     728           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_bwr_from_samplerate( LC3PLUS_RTP_FTD_BWR *bwr, const int32_t sampling_rate, const int32_t high_res_enabled )
     729             : {
     730           0 :     if ( NULL == bwr )
     731             :     {
     732           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     733             :     }
     734           0 :     switch ( sampling_rate )
     735             :     {
     736           0 :         case 8000:
     737           0 :             if ( high_res_enabled )
     738             :             {
     739           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     740             :             }
     741           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_NB;
     742           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     743           0 :         case 16000:
     744           0 :             if ( high_res_enabled )
     745             :             {
     746           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     747             :             }
     748           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_WB;
     749           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     750           0 :         case 24000:
     751           0 :             if ( high_res_enabled )
     752             :             {
     753           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     754             :             }
     755           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_SSWB;
     756           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     757           0 :         case 32000:
     758           0 :             if ( high_res_enabled )
     759             :             {
     760           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     761             :             }
     762           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_SWB;
     763           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     764           0 :         case 44100:
     765           0 :             if ( high_res_enabled )
     766             :             {
     767           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     768             :             }
     769           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_FBCD;
     770           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     771           0 :         case 48000:
     772           0 :             if ( 0 == high_res_enabled )
     773             :             {
     774           0 :                 *bwr = LC3PLUS_RTP_FTD_BWR_FB;
     775           0 :                 return LC3PLUS_RTP_ERR_NO_ERROR;
     776             :             }
     777             :             else
     778             :             {
     779           0 :                 *bwr = LC3PLUS_RTP_FTD_BWR_FBHR;
     780           0 :                 return LC3PLUS_RTP_ERR_NO_ERROR;
     781             :             }
     782           0 :         case 96000:
     783           0 :             if ( 0 == high_res_enabled )
     784             :             {
     785           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     786             :             }
     787           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_UBHR;
     788           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     789           0 :         default:
     790           0 :             break;
     791             :     }
     792             : 
     793           0 :     return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     794             : }
     795             : 
     796           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( LC3PLUS_RTP_FTD_FDI *fdi, const int32_t frame_duration_us )
     797             : {
     798           0 :     if ( NULL == fdi )
     799             :     {
     800           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     801             :     }
     802           0 :     switch ( frame_duration_us )
     803             :     {
     804           0 :         case 2500:
     805           0 :             *fdi = LC3PLUS_RTP_FTD_FDI_2500_US;
     806           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     807           0 :         case 5000:
     808           0 :             *fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
     809           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     810           0 :         case 10000:
     811           0 :             *fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
     812           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     813           0 :         default:
     814           0 :             break;
     815             :     }
     816             : 
     817           0 :     return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     818             : }

Generated by: LCOV version 1.14