LCOV - code coverage report
Current view: top level - lib_isar - isar_lc3plus_payload.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 0 419 0.0 %
Date: 2025-05-23 08:37:30 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             : 
      40             : /*-------------------------------------------------------------------------
      41             :  * Local functions
      42             :  *------------------------------------------------------------------------*/
      43             : 
      44           0 : static LC3PLUS_RTP_ERR s_frame_duration_ms_from_fdi(
      45             :     int32_t *frame_duration_us,
      46             :     const LC3PLUS_RTP_FTD_FDI fdi )
      47             : {
      48           0 :     if ( NULL == frame_duration_us )
      49             :     {
      50           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
      51             :     }
      52           0 :     switch ( fdi )
      53             :     {
      54           0 :         case LC3PLUS_RTP_FTD_FDI_2500_US:
      55           0 :             *frame_duration_us = 2500;
      56           0 :             break;
      57           0 :         case LC3PLUS_RTP_FTD_FDI_5000_US:
      58           0 :             *frame_duration_us = 5000;
      59           0 :             break;
      60           0 :         case LC3PLUS_RTP_FTD_FDI_10000_US:
      61           0 :             *frame_duration_us = 10000;
      62           0 :             break;
      63           0 :         case LC3PLUS_RTP_FTD_FDI_RESERVED:
      64             :         default:
      65           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
      66             :     }
      67             : 
      68           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
      69             : }
      70             : 
      71             : 
      72           0 : static LC3PLUS_RTP_ERR s_sampling_rate_hz_from_bwr(
      73             :     int32_t *sample_rate_hz,
      74             :     const LC3PLUS_RTP_FTD_BWR bwr )
      75             : {
      76           0 :     if ( NULL == sample_rate_hz )
      77             :     {
      78           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
      79             :     }
      80           0 :     switch ( bwr )
      81             :     {
      82           0 :         case LC3PLUS_RTP_FTD_BWR_NB:
      83           0 :             *sample_rate_hz = 8000;
      84           0 :             break;
      85           0 :         case LC3PLUS_RTP_FTD_BWR_WB:
      86           0 :             *sample_rate_hz = 16000;
      87           0 :             break;
      88           0 :         case LC3PLUS_RTP_FTD_BWR_SSWB:
      89           0 :             *sample_rate_hz = 24000;
      90           0 :             break;
      91           0 :         case LC3PLUS_RTP_FTD_BWR_SWB:
      92           0 :             *sample_rate_hz = 32000;
      93           0 :             break;
      94           0 :         case LC3PLUS_RTP_FTD_BWR_FBCD:
      95           0 :             *sample_rate_hz = 44100;
      96           0 :             break;
      97           0 :         case LC3PLUS_RTP_FTD_BWR_FB:
      98           0 :             *sample_rate_hz = 48000;
      99           0 :             break;
     100           0 :         case LC3PLUS_RTP_FTD_BWR_FBHR:
     101           0 :             *sample_rate_hz = 48000;
     102           0 :             break;
     103           0 :         case LC3PLUS_RTP_FTD_BWR_UBHR:
     104           0 :             *sample_rate_hz = 96000;
     105           0 :             break;
     106           0 :         default:
     107           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     108             :     }
     109             : 
     110           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     111             : }
     112             : 
     113             : 
     114           0 : static LC3PLUS_RTP_ERR s_high_resolution_flag_from_bwr(
     115             :     int16_t *high_resolution_flag,
     116             :     const LC3PLUS_RTP_FTD_BWR bwr )
     117             : {
     118           0 :     if ( NULL == high_resolution_flag )
     119             :     {
     120           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     121             :     }
     122           0 :     switch ( bwr )
     123             :     {
     124           0 :         case LC3PLUS_RTP_FTD_BWR_NB:
     125           0 :             *high_resolution_flag = 0;
     126           0 :             break;
     127           0 :         case LC3PLUS_RTP_FTD_BWR_WB:
     128           0 :             *high_resolution_flag = 0;
     129           0 :             break;
     130           0 :         case LC3PLUS_RTP_FTD_BWR_SSWB:
     131           0 :             *high_resolution_flag = 0;
     132           0 :             break;
     133           0 :         case LC3PLUS_RTP_FTD_BWR_SWB:
     134           0 :             *high_resolution_flag = 0;
     135           0 :             break;
     136           0 :         case LC3PLUS_RTP_FTD_BWR_FBCD:
     137           0 :             *high_resolution_flag = 0;
     138           0 :             break;
     139           0 :         case LC3PLUS_RTP_FTD_BWR_FB:
     140           0 :             *high_resolution_flag = 0;
     141           0 :             break;
     142           0 :         case LC3PLUS_RTP_FTD_BWR_FBHR:
     143           0 :             *high_resolution_flag = 1;
     144           0 :             break;
     145           0 :         case LC3PLUS_RTP_FTD_BWR_UBHR:
     146           0 :             *high_resolution_flag = 1;
     147           0 :             break;
     148           0 :         default:
     149           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     150             :     }
     151             : 
     152           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     153             : }
     154             : 
     155             : 
     156             : /*-------------------------------------------------------------------------
     157             :  * LC3PLUS_RTP_frame_data_length_get_size()
     158             :  *
     159             :  *
     160             :  *------------------------------------------------------------------------*/
     161             : 
     162           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size(
     163             :     int32_t *length,
     164             :     const LC3PLUS_RTP_FDL frameDataLengthValue )
     165             : {
     166           0 :     if ( frameDataLengthValue == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_BAD || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_SID )
     167             :     {
     168           0 :         *length = 1;
     169             :     }
     170           0 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_1_MAX )
     171             :     {
     172           0 :         *length = 1;
     173             :     }
     174           0 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_2_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_2_MAX )
     175             :     {
     176           0 :         *length = 2;
     177             :     }
     178           0 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_3_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
     179             :     {
     180           0 :         *length = 3;
     181             :     }
     182             :     else
     183             :     {
     184           0 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     185             :     }
     186             : 
     187           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     188             : }
     189             : 
     190             : 
     191           0 : static LC3PLUS_RTP_ERR s_frame_data_length_pack(
     192             :     const LC3PLUS_RTP_FDL frameDataLengthValue,
     193             :     uint8_t *dst )
     194             : {
     195             :     int32_t frame_data_length_size;
     196             :     LC3PLUS_RTP_ERR err;
     197             : 
     198           0 :     if ( NULL == dst )
     199             :     {
     200           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     201             :     }
     202             : 
     203           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, frameDataLengthValue );
     204           0 :     if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
     205             :     {
     206           0 :         return err;
     207             :     }
     208           0 :     if ( 1 == frame_data_length_size )
     209             :     {
     210           0 :         *dst++ = frameDataLengthValue >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     211             :     }
     212           0 :     else if ( 2 == frame_data_length_size )
     213             :     {
     214           0 :         const int32_t frameDataLengthValueToWrite = frameDataLengthValue - LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     215           0 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     216           0 :         *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     217             :     }
     218           0 :     else if ( 3 == frame_data_length_size )
     219             :     {
     220           0 :         const int32_t frameDataLengthValueToWrite = frameDataLengthValue - ( 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE );
     221           0 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     222           0 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     223           0 :         *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     224             :     }
     225             : 
     226           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     227             : }
     228             : 
     229             : 
     230           0 : static int32_t s_get_size_from_fdl(
     231             :     const LC3PLUS_RTP_FDL fdl )
     232             : {
     233           0 :     if ( fdl >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
     234             :     {
     235           0 :         return fdl;
     236             :     }
     237             : 
     238           0 :     return 0;
     239             : }
     240             : 
     241             : 
     242           0 : static bool s_fdl_is_magic_value(
     243             :     const LC3PLUS_RTP_FDL fdl )
     244             : {
     245           0 :     if ( fdl == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || fdl == LC3PLUS_RTP_FDL_SPEECH_SID || fdl == LC3PLUS_RTP_FDL_SPEECH_BAD )
     246             :     {
     247           0 :         return true;
     248             :     }
     249             : 
     250           0 :     return false;
     251             : }
     252             : 
     253             : 
     254           0 : static bool s_fdl_value_is_valid_request(
     255             :     const LC3PLUS_RTP_FDL fdl_request )
     256             : {
     257             :     /* LC3PLUS_RTP_FDL_SPEECH_SID && LC3PLUS_RTP_FDL_SPEECH_SID are not valid values for the FDL request */
     258           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 ) )
     259             :     {
     260           0 :         return true;
     261             :     }
     262             : 
     263           0 :     return false;
     264             : }
     265             : 
     266             : 
     267           0 : static LC3PLUS_RTP_ERR s_frame_data_length_parse(
     268             :     LC3PLUS_RTP_FDL *frame_data_length_value,
     269             :     const uint8_t *src,
     270             :     const size_t remaining_capacity )
     271             : {
     272             :     int32_t frame_data_length_size;
     273             :     LC3PLUS_RTP_ERR err;
     274             : 
     275           0 :     if ( NULL == src || NULL == frame_data_length_value || remaining_capacity < 1 )
     276             :     {
     277           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     278             :     }
     279             : 
     280           0 :     if ( remaining_capacity > 2 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *( src + 1 ) )
     281             :     {
     282           0 :         *frame_data_length_value = *( src + 2 ) + 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     283             :     }
     284           0 :     else if ( remaining_capacity > 1 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src )
     285             :     {
     286           0 :         *frame_data_length_value = *( src + 1 ) + 1 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     287             :     }
     288           0 :     else if ( remaining_capacity > 0 )
     289             :     {
     290           0 :         *frame_data_length_value = *src << 0;
     291             :     }
     292             :     else
     293             :     {
     294           0 :         return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     295             :     }
     296             : 
     297             :     /* sanity check */
     298           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, *frame_data_length_value );
     299           0 :     if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
     300             :     {
     301           0 :         return err;
     302             :     }
     303             : 
     304           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     305             : }
     306             : 
     307             : 
     308           0 : static LC3PLUS_RTP_ERR s_parse_ftd(
     309             :     const uint8_t *p_read,
     310             :     LC3PLUS_RTP_FTD *receiver_ftd,
     311             :     int32_t *num_bytes_read,
     312             :     const size_t remaining_capacity )
     313             : {
     314             :     int32_t frame_data_block_size;
     315             :     LC3PLUS_RTP_FDL fdl;
     316             :     LC3PLUS_RTP_ERR err;
     317             : 
     318           0 :     if ( NULL == p_read || NULL == receiver_ftd || NULL == num_bytes_read || remaining_capacity < LC3PLUS_RTP_FTD_MIN_SIZE )
     319             :     {
     320           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     321             :     }
     322             : 
     323           0 :     *num_bytes_read = 0;
     324           0 :     receiver_ftd->fc = 0;
     325           0 :     receiver_ftd->fdi = 0;
     326           0 :     receiver_ftd->bwr = 0;
     327           0 :     receiver_ftd->h = 0;
     328           0 :     receiver_ftd->fc |= *p_read & LC3PLUS_RTP_FTD_FC_MASK;
     329           0 :     receiver_ftd->fdi |= ( *p_read & LC3PLUS_RTP_FTD_FDI_MASK );
     330           0 :     receiver_ftd->bwr |= ( *p_read & LC3PLUS_RTP_FTD_BWR_MASK );
     331           0 :     receiver_ftd->h |= ( *p_read & LC3PLUS_RTP_FTD_H_MASK );
     332           0 :     p_read++;
     333           0 :     *num_bytes_read = 1;
     334             : 
     335           0 :     err = s_frame_data_length_parse( &fdl, p_read, remaining_capacity - *num_bytes_read );
     336           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     337             :     {
     338           0 :         return err;
     339             :     }
     340           0 :     frame_data_block_size = s_get_size_from_fdl( fdl );
     341             : 
     342           0 :     receiver_ftd->frame_data_length = frame_data_block_size;
     343             :     int32_t length_field_size;
     344           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &length_field_size, receiver_ftd->frame_data_length );
     345           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     346             :     {
     347           0 :         return err;
     348             :     }
     349           0 :     *num_bytes_read += length_field_size;
     350             : 
     351           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     352             : }
     353             : 
     354             : 
     355             : /*-------------------------------------------------------------------------
     356             :  * LC3PLUS_RTP_payload_serialize()
     357             :  *
     358             :  *
     359             :  *------------------------------------------------------------------------*/
     360             : 
     361           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_serialize(
     362             :     uint8_t *serialized_buffer,
     363             :     const size_t serialized_buffer_capacity,
     364             :     size_t *packed_buffer_actual_size,
     365             :     const LC3PLUS_RTP_FDL fdl_request,
     366             :     LC3PLUS_RTP_FTD *sender_ftds,
     367             :     const size_t sender_ftds_num )
     368             : {
     369             :     LC3PLUS_RTP_ERR err;
     370           0 :     uint8_t *p_write = serialized_buffer;
     371             :     uint32_t i;
     372           0 :     int32_t bytes_written = 0;
     373             :     int32_t lc3plus_frame_size_sum;
     374             :     uint8_t *p_frame_data;
     375             :     int32_t fdl_request_length;
     376             : 
     377           0 :     if ( NULL == serialized_buffer || NULL == packed_buffer_actual_size || NULL == sender_ftds )
     378             :     {
     379           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     380             :     }
     381             : 
     382           0 :     *packed_buffer_actual_size = 0;
     383           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, fdl_request );
     384           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     385             :     {
     386           0 :         return err;
     387             :     }
     388           0 :     if ( !s_fdl_value_is_valid_request( fdl_request ) )
     389             :     {
     390           0 :         return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
     391             :     }
     392           0 :     if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_request_length )
     393             :     {
     394           0 :         return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     395             :     }
     396           0 :     err = s_frame_data_length_pack( fdl_request, p_write );
     397           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     398             :     {
     399           0 :         return err;
     400             :     }
     401           0 :     bytes_written += fdl_request_length;
     402           0 :     p_write += bytes_written;
     403             : 
     404           0 :     for ( i = 0; i < sender_ftds_num; ++i )
     405             :     {
     406             :         /* only the last ftd may have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */
     407           0 :         if ( sender_ftds[i].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i != ( sender_ftds_num - 1 ) )
     408             :         {
     409           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     410             :         }
     411             :         /* the last ftd must have the LC3PLUS_RTP_FTD_FC_LAST_OVERALL value */
     412           0 :         if ( sender_ftds[i].fc != LC3PLUS_RTP_FTD_FC_LAST_OVERALL && i == ( sender_ftds_num - 1 ) )
     413             :         {
     414           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     415             :         }
     416           0 :         if ( (int32_t) serialized_buffer_capacity < bytes_written + LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL )
     417             :         {
     418           0 :             return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     419             :         }
     420           0 :         *p_write = 0x00;
     421           0 :         *p_write |= LC3PLUS_RTP_FTD_FC_MASK & (uint8_t) sender_ftds[i].fc;
     422           0 :         *p_write |= LC3PLUS_RTP_FTD_FDI_MASK & (uint8_t) sender_ftds[i].fdi;
     423           0 :         *p_write |= LC3PLUS_RTP_FTD_BWR_MASK & (uint8_t) sender_ftds[i].bwr;
     424           0 :         *p_write |= LC3PLUS_RTP_FTD_H_MASK & (uint8_t) sender_ftds[i].h;
     425           0 :         p_write++;
     426           0 :         bytes_written += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
     427             : 
     428             :         int32_t fdl_length;
     429           0 :         err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_length, sender_ftds[i].frame_data_length );
     430           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     431             :         {
     432           0 :             return err;
     433             :         }
     434           0 :         if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_length )
     435             :         {
     436           0 :             return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     437             :         }
     438           0 :         err = s_frame_data_length_pack( sender_ftds[i].frame_data_length, p_write );
     439           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     440             :         {
     441           0 :             return err;
     442             :         }
     443           0 :         p_write += fdl_length;
     444           0 :         bytes_written += fdl_length;
     445             :     }
     446             : 
     447           0 :     lc3plus_frame_size_sum = 0;
     448           0 :     p_frame_data = serialized_buffer + bytes_written;
     449           0 :     for ( i = 0; i < sender_ftds_num; ++i )
     450             :     {
     451           0 :         sender_ftds[i].frame_data = p_frame_data;
     452           0 :         p_frame_data += sender_ftds[i].frame_data_length;
     453           0 :         lc3plus_frame_size_sum += sender_ftds[i].frame_data_length;
     454             :     }
     455           0 :     *packed_buffer_actual_size = bytes_written + lc3plus_frame_size_sum;
     456           0 :     assert( *packed_buffer_actual_size <= serialized_buffer_capacity );
     457             : 
     458           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     459             : }
     460             : 
     461             : 
     462           0 : static LC3PLUS_RTP_ERR s_ftds_parse(
     463             :     LC3PLUS_RTP_FTD *receiver_ftds,
     464             :     const int32_t receiver_ftds_num_max,
     465             :     int16_t *receiver_ftds_num,
     466             :     uint8_t *serialized_buffer,
     467             :     const size_t serialized_buffer_size )
     468             : {
     469             :     int32_t diff;
     470             :     uint8_t *p_read;
     471           0 :     uint32_t ftds_offset_sum = 0;
     472             :     int16_t i;
     473             :     LC3PLUS_RTP_ERR error;
     474             :     int32_t frame_offset_counter;
     475             :     int32_t size;
     476             : 
     477           0 :     p_read = serialized_buffer;
     478           0 :     if ( NULL == receiver_ftds || NULL == receiver_ftds_num || NULL == serialized_buffer )
     479             :     {
     480           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     481             :     }
     482           0 :     if ( 0 == serialized_buffer_size )
     483             :     {
     484           0 :         return LC3PLUS_RTP_ERR_EMPTY_TOC;
     485             :     }
     486           0 :     if ( receiver_ftds_num_max <= 0 )
     487             :     {
     488           0 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     489             :     }
     490             : 
     491             :     {
     492           0 :         int32_t num_bytes_read_sum = 0;
     493           0 :         const int32_t min_num_bytes_per_ftd = 2;
     494           0 :         int16_t receiver_ftds_index = 0;
     495           0 :         bool another_ftd = true;
     496             :         int32_t num_bytes_read_per_ftd;
     497             : 
     498           0 :         while ( another_ftd )
     499             :         {
     500           0 :             if ( (int32_t) serialized_buffer_size < min_num_bytes_per_ftd )
     501             :             {
     502           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     503             :             }
     504           0 :             if ( num_bytes_read_sum >= (int32_t) serialized_buffer_size - min_num_bytes_per_ftd )
     505             :             {
     506           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     507             :             }
     508           0 :             num_bytes_read_per_ftd = 0;
     509           0 :             error = s_parse_ftd( p_read, &receiver_ftds[receiver_ftds_index], &num_bytes_read_per_ftd, serialized_buffer_size - num_bytes_read_sum );
     510           0 :             if ( LC3PLUS_RTP_ERR_NO_ERROR != error )
     511             :             {
     512           0 :                 return error;
     513             :             }
     514           0 :             p_read += num_bytes_read_per_ftd;
     515           0 :             num_bytes_read_sum += num_bytes_read_per_ftd;
     516             : 
     517           0 :             if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_RESERVED )
     518             :             {
     519           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
     520             :             }
     521           0 :             else if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL )
     522             :             {
     523           0 :                 another_ftd = false;
     524             :             }
     525             : 
     526           0 :             if ( another_ftd )
     527             :             {
     528           0 :                 if ( receiver_ftds_index >= receiver_ftds_num_max )
     529             :                 {
     530           0 :                     return LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED;
     531             :                 }
     532           0 :                 ( receiver_ftds_index )++;
     533             :             }
     534             :         }
     535           0 :         *receiver_ftds_num = receiver_ftds_index + 1;
     536             :     }
     537             : 
     538             :     /* set frame-data pointers into serialized_buffer */
     539           0 :     for ( i = 0; i < *receiver_ftds_num; ++i )
     540             :     {
     541           0 :         error = LC3PLUS_RTP_frame_data_length_get_size( &size, receiver_ftds[i].frame_data_length );
     542           0 :         if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
     543             :         {
     544           0 :             return error;
     545             :         }
     546           0 :         ftds_offset_sum += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + size;
     547             :     }
     548             : 
     549           0 :     frame_offset_counter = 0;
     550           0 :     for ( i = 0; i < *receiver_ftds_num; ++i )
     551             :     {
     552           0 :         if ( s_fdl_is_magic_value( receiver_ftds[i].frame_data_length ) )
     553             :         {
     554           0 :             receiver_ftds[i].frame_data = NULL;
     555             :         }
     556             :         else
     557             :         {
     558           0 :             receiver_ftds[i].frame_data = serialized_buffer + ftds_offset_sum + frame_offset_counter;
     559           0 :             frame_offset_counter += receiver_ftds[i].frame_data_length;
     560             :         }
     561             :     }
     562             : 
     563           0 :     if ( ftds_offset_sum + frame_offset_counter != serialized_buffer_size )
     564             :     {
     565             :         /* parsed content & size n bytes of input buffer do not line up */
     566             :         /* 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 */
     567           0 :         diff = serialized_buffer_size - ( ftds_offset_sum + frame_offset_counter );
     568           0 :         if ( diff < 0 )
     569             :         {
     570           0 :             return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     571             :         }
     572             :         /* verify that all bytes are zero */
     573           0 :         p_read += frame_offset_counter;
     574           0 :         for ( i = 0; i < diff; ++i )
     575             :         {
     576           0 :             if ( *p_read != 0 )
     577             :             {
     578             :                 /* non-zero byte in padding region */
     579           0 :                 return LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES;
     580             :             }
     581           0 :             p_read++;
     582             :         }
     583             :     }
     584             : 
     585           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     586             : }
     587             : 
     588             : 
     589             : /*-------------------------------------------------------------------------
     590             :  * LC3PLUS_RTP_payload_deserialize()
     591             :  *
     592             :  *
     593             :  *------------------------------------------------------------------------*/
     594             : 
     595           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_payload_deserialize(
     596             :     LC3PLUS_RTP_PAYLOAD *payload,
     597             :     uint8_t *serialized_buffer,
     598             :     const size_t serialized_buffer_size )
     599             : {
     600             :     int32_t new_frame_duration_us;
     601             :     int32_t new_sampling_rate_hz;
     602             :     int16_t new_high_resolution_flag;
     603           0 :     int16_t i = 0;
     604           0 :     int16_t channel_id = 0;
     605           0 :     int16_t media_time_id = 0;
     606           0 :     const int16_t invalid_value = -1;
     607             :     int16_t media_times_per_channel[LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS];
     608             :     int16_t channels_per_media_time[LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES];
     609             :     LC3PLUS_RTP_ERR err;
     610             : 
     611           0 :     if ( NULL == payload || NULL == serialized_buffer )
     612             :     {
     613           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     614             :     }
     615           0 :     if ( 0 == serialized_buffer_size )
     616             :     {
     617           0 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     618             :     }
     619             : 
     620           0 :     for ( media_time_id = 0; media_time_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++media_time_id )
     621             :     {
     622           0 :         channels_per_media_time[media_time_id] = invalid_value;
     623             :     }
     624           0 :     media_time_id = 0;
     625           0 :     for ( channel_id = 0; channel_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++channel_id )
     626             :     {
     627           0 :         media_times_per_channel[channel_id] = invalid_value;
     628             :     }
     629           0 :     channel_id = 0;
     630             : 
     631           0 :     err = s_frame_data_length_parse( &payload->fdl_request, serialized_buffer, serialized_buffer_size );
     632           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     633             :     {
     634           0 :         return err;
     635             :     }
     636             :     int32_t fdl_request_length;
     637           0 :     err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, payload->fdl_request );
     638           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     639             :     {
     640           0 :         return err;
     641             :     }
     642           0 :     if ( !s_fdl_value_is_valid_request( payload->fdl_request ) )
     643             :     {
     644           0 :         return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
     645             :     }
     646             : 
     647           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 );
     648           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     649             :     {
     650           0 :         return err;
     651             :     }
     652           0 :     if ( 0 == payload->num_ftds )
     653             :     {
     654           0 :         return LC3PLUS_RTP_ERR_GENERIC_ERROR;
     655             :     }
     656             :     /* verify shared setting between all FTDs [samplerate, frame_duration, channel count] */
     657             : 
     658             :     /* initialize on the first FTD, use this as reference */
     659           0 :     err = s_frame_duration_ms_from_fdi( &payload->frame_duration_us, payload->ftds[0].fdi );
     660           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     661             :     {
     662           0 :         return err;
     663             :     }
     664           0 :     err = s_sampling_rate_hz_from_bwr( &payload->sampling_rate_hz, payload->ftds[0].bwr );
     665           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     666             :     {
     667           0 :         return err;
     668             :     }
     669           0 :     err = s_high_resolution_flag_from_bwr( &payload->high_resolution_enabled, payload->ftds[0].bwr );
     670           0 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     671             :     {
     672           0 :         return err;
     673             :     }
     674           0 :     payload->num_channels = 0;
     675           0 :     payload->num_media_times = 0;
     676           0 :     for ( i = 0; i < payload->num_ftds; ++i )
     677             :     {
     678           0 :         if ( payload->ftds[i].h != LC3PLUS_RTP_FTD_H_PRIMARY )
     679             :         {
     680             :             /* not implemented */
     681           0 :             return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     682             :         }
     683             : 
     684           0 :         err = s_frame_duration_ms_from_fdi( &new_frame_duration_us, payload->ftds[i].fdi );
     685           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     686             :         {
     687           0 :             return err;
     688             :         }
     689           0 :         if ( payload->frame_duration_us != new_frame_duration_us )
     690             :         {
     691             :             /* mixed frame durations not supported */
     692           0 :             return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
     693             :         }
     694             : 
     695           0 :         err = s_sampling_rate_hz_from_bwr( &new_sampling_rate_hz, payload->ftds[i].bwr );
     696           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     697             :         {
     698           0 :             return err;
     699             :         }
     700           0 :         if ( payload->sampling_rate_hz != new_sampling_rate_hz )
     701             :         {
     702             :             /* mixed sampling frequencies not supported */
     703           0 :             return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
     704             :         }
     705             : 
     706             : 
     707           0 :         err = s_high_resolution_flag_from_bwr( &new_high_resolution_flag, payload->ftds[i].bwr );
     708           0 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     709             :         {
     710           0 :             return err;
     711             :         }
     712           0 :         if ( payload->high_resolution_enabled != new_high_resolution_flag )
     713             :         {
     714             :             /* mixed high resolution mode not supported */
     715           0 :             return LC3PLUS_RTP_ERR_UNSUPPORTED_CONFIGURATION;
     716             :         }
     717             : 
     718           0 :         switch ( payload->ftds[i].fc )
     719             :         {
     720           0 :             case LC3PLUS_RTP_FTD_FC_LAST_OVERALL:
     721           0 :                 channels_per_media_time[media_time_id]++;
     722           0 :                 media_times_per_channel[channel_id]++;
     723           0 :                 channel_id = 0;
     724           0 :                 media_time_id = 0;
     725           0 :                 break;
     726           0 :             case LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL:
     727           0 :                 media_times_per_channel[channel_id]++;
     728           0 :                 channels_per_media_time[media_time_id]++;
     729           0 :                 channel_id++;
     730           0 :                 break;
     731           0 :             case LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME:
     732           0 :                 media_times_per_channel[channel_id]++;
     733           0 :                 channels_per_media_time[media_time_id]++;
     734           0 :                 channel_id = 0;
     735           0 :                 media_time_id++;
     736           0 :                 break;
     737           0 :             case LC3PLUS_RTP_FTD_FC_RESERVED:
     738             :             default:
     739           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
     740             :         }
     741             :     }
     742             : 
     743             :     {
     744             :         int32_t valid_num_media_times_per_channel;
     745             :         int32_t iCh;
     746             :         /* check whether all channels exist for each media time */
     747           0 :         if ( media_times_per_channel[0] == invalid_value )
     748             :         {
     749           0 :             return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     750             :         }
     751           0 :         valid_num_media_times_per_channel = media_times_per_channel[0];
     752           0 :         for ( iCh = 0; iCh < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++iCh )
     753             :         {
     754           0 :             if ( media_times_per_channel[iCh] == invalid_value )
     755             :             {
     756           0 :                 break;
     757             :             }
     758           0 :             if ( valid_num_media_times_per_channel != media_times_per_channel[iCh] )
     759             :             {
     760           0 :                 return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     761             :             }
     762             :         }
     763             :     }
     764             :     {
     765             :         /*  whether all media times exist for each channel */
     766             :         int32_t iMediaTime;
     767             :         int32_t valid_num_channels_per_media_time;
     768           0 :         if ( channels_per_media_time[0] == invalid_value )
     769             :         {
     770           0 :             return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     771             :         }
     772           0 :         valid_num_channels_per_media_time = channels_per_media_time[0];
     773           0 :         for ( iMediaTime = 0; iMediaTime < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++iMediaTime )
     774             :         {
     775           0 :             if ( channels_per_media_time[iMediaTime] == invalid_value )
     776             :             {
     777           0 :                 break;
     778             :             }
     779           0 :             if ( valid_num_channels_per_media_time != channels_per_media_time[iMediaTime] )
     780             :             {
     781           0 :                 return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     782             :             }
     783             :         }
     784             :     }
     785             : 
     786             :     /* convert zero-index to count */
     787           0 :     payload->num_channels = channels_per_media_time[0] + 1;
     788           0 :     payload->num_media_times = media_times_per_channel[0] + 1;
     789             : 
     790             :     /* verify that all media times have the same number of channels, partial packets are not supported */
     791           0 :     if ( payload->num_ftds != payload->num_channels * payload->num_media_times )
     792             :     {
     793           0 :         return LC3PLUS_RTP_ERR_GENERIC_ERROR;
     794             :     }
     795             : 
     796           0 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     797             : }
     798             : 
     799             : 
     800             : /*-------------------------------------------------------------------------
     801             :  * LC3PLUS_RTP_ftd_bwr_from_samplerate()
     802             :  *
     803             :  *
     804             :  *------------------------------------------------------------------------*/
     805             : 
     806           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_bwr_from_samplerate(
     807             :     LC3PLUS_RTP_FTD_BWR *bwr,
     808             :     const int32_t sampling_rate,
     809             :     const int32_t high_res_enabled )
     810             : {
     811           0 :     if ( NULL == bwr )
     812             :     {
     813           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     814             :     }
     815           0 :     switch ( sampling_rate )
     816             :     {
     817           0 :         case 8000:
     818           0 :             if ( high_res_enabled )
     819             :             {
     820           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     821             :             }
     822           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_NB;
     823           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     824           0 :         case 16000:
     825           0 :             if ( high_res_enabled )
     826             :             {
     827           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     828             :             }
     829           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_WB;
     830           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     831           0 :         case 24000:
     832           0 :             if ( high_res_enabled )
     833             :             {
     834           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     835             :             }
     836           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_SSWB;
     837           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     838           0 :         case 32000:
     839           0 :             if ( high_res_enabled )
     840             :             {
     841           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     842             :             }
     843           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_SWB;
     844           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     845           0 :         case 44100:
     846           0 :             if ( high_res_enabled )
     847             :             {
     848           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     849             :             }
     850           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_FBCD;
     851           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     852           0 :         case 48000:
     853           0 :             if ( 0 == high_res_enabled )
     854             :             {
     855           0 :                 *bwr = LC3PLUS_RTP_FTD_BWR_FB;
     856           0 :                 return LC3PLUS_RTP_ERR_NO_ERROR;
     857             :             }
     858             :             else
     859             :             {
     860           0 :                 *bwr = LC3PLUS_RTP_FTD_BWR_FBHR;
     861           0 :                 return LC3PLUS_RTP_ERR_NO_ERROR;
     862             :             }
     863           0 :         case 96000:
     864           0 :             if ( 0 == high_res_enabled )
     865             :             {
     866           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     867             :             }
     868           0 :             *bwr = LC3PLUS_RTP_FTD_BWR_UBHR;
     869           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     870           0 :         default:
     871           0 :             break;
     872             :     }
     873             : 
     874           0 :     return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     875             : }
     876             : 
     877             : 
     878             : /*-------------------------------------------------------------------------
     879             :  * LC3PLUS_RTP_ftd_fdi_from_frame_duration_us()
     880             :  *
     881             :  *
     882             :  *------------------------------------------------------------------------*/
     883             : 
     884           0 : LC3PLUS_RTP_ERR LC3PLUS_RTP_ftd_fdi_from_frame_duration_us(
     885             :     LC3PLUS_RTP_FTD_FDI *fdi,
     886             :     const int32_t frame_duration_us )
     887             : {
     888           0 :     if ( NULL == fdi )
     889             :     {
     890           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     891             :     }
     892           0 :     switch ( frame_duration_us )
     893             :     {
     894           0 :         case 2500:
     895           0 :             *fdi = LC3PLUS_RTP_FTD_FDI_2500_US;
     896           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     897           0 :         case 5000:
     898           0 :             *fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
     899           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     900           0 :         case 10000:
     901           0 :             *fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
     902           0 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     903           0 :         default:
     904           0 :             break;
     905             :     }
     906             : 
     907           0 :     return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     908             : }

Generated by: LCOV version 1.14