LCOV - code coverage report
Current view: top level - lib_isar - isar_lc3plus_payload.c (source / functions) Hit Total Coverage
Test: Coverage on main -- merged total coverage @ 9b04ec3cb36f5e8dc438cf854fa3e349998fa1e9 Lines: 295 419 70.4 %
Date: 2025-10-31 05:45:46 Functions: 15 15 100.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     2018091 : 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     2018091 :     if ( NULL == frame_duration_us )
      49             :     {
      50           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
      51             :     }
      52     2018091 :     switch ( fdi )
      53             :     {
      54          17 :         case LC3PLUS_RTP_FTD_FDI_2500_US:
      55          17 :             *frame_duration_us = 2500;
      56          17 :             break;
      57     1910298 :         case LC3PLUS_RTP_FTD_FDI_5000_US:
      58     1910298 :             *frame_duration_us = 5000;
      59     1910298 :             break;
      60      107776 :         case LC3PLUS_RTP_FTD_FDI_10000_US:
      61      107776 :             *frame_duration_us = 10000;
      62      107776 :             break;
      63           0 :         case LC3PLUS_RTP_FTD_FDI_RESERVED:
      64             :         default:
      65           0 :             return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
      66             :     }
      67             : 
      68     2018091 :     return LC3PLUS_RTP_ERR_NO_ERROR;
      69             : }
      70             : 
      71             : 
      72     2018091 : 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     2018091 :     if ( NULL == sample_rate_hz )
      77             :     {
      78           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
      79             :     }
      80     2018091 :     switch ( bwr )
      81             :     {
      82           0 :         case LC3PLUS_RTP_FTD_BWR_NB:
      83           0 :             *sample_rate_hz = 8000;
      84           0 :             break;
      85           5 :         case LC3PLUS_RTP_FTD_BWR_WB:
      86           5 :             *sample_rate_hz = 16000;
      87           5 :             break;
      88           0 :         case LC3PLUS_RTP_FTD_BWR_SSWB:
      89           0 :             *sample_rate_hz = 24000;
      90           0 :             break;
      91           5 :         case LC3PLUS_RTP_FTD_BWR_SWB:
      92           5 :             *sample_rate_hz = 32000;
      93           5 :             break;
      94           0 :         case LC3PLUS_RTP_FTD_BWR_FBCD:
      95           0 :             *sample_rate_hz = 44100;
      96           0 :             break;
      97     2018081 :         case LC3PLUS_RTP_FTD_BWR_FB:
      98     2018081 :             *sample_rate_hz = 48000;
      99     2018081 :             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     2018091 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     111             : }
     112             : 
     113             : 
     114     2018091 : 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     2018091 :     if ( NULL == high_resolution_flag )
     119             :     {
     120           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     121             :     }
     122     2018091 :     switch ( bwr )
     123             :     {
     124           0 :         case LC3PLUS_RTP_FTD_BWR_NB:
     125           0 :             *high_resolution_flag = 0;
     126           0 :             break;
     127           5 :         case LC3PLUS_RTP_FTD_BWR_WB:
     128           5 :             *high_resolution_flag = 0;
     129           5 :             break;
     130           0 :         case LC3PLUS_RTP_FTD_BWR_SSWB:
     131           0 :             *high_resolution_flag = 0;
     132           0 :             break;
     133           5 :         case LC3PLUS_RTP_FTD_BWR_SWB:
     134           5 :             *high_resolution_flag = 0;
     135           5 :             break;
     136           0 :         case LC3PLUS_RTP_FTD_BWR_FBCD:
     137           0 :             *high_resolution_flag = 0;
     138           0 :             break;
     139     2018081 :         case LC3PLUS_RTP_FTD_BWR_FB:
     140     2018081 :             *high_resolution_flag = 0;
     141     2018081 :             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     2018091 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     153             : }
     154             : 
     155             : 
     156             : /*-------------------------------------------------------------------------
     157             :  * LC3PLUS_RTP_frame_data_length_get_size()
     158             :  *
     159             :  *
     160             :  *------------------------------------------------------------------------*/
     161             : 
     162    14444093 : LC3PLUS_RTP_ERR LC3PLUS_RTP_frame_data_length_get_size(
     163             :     int32_t *length,
     164             :     const LC3PLUS_RTP_FDL frameDataLengthValue )
     165             : {
     166    14444093 :     if ( frameDataLengthValue == LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_BAD || frameDataLengthValue == LC3PLUS_RTP_FDL_SPEECH_SID )
     167             :     {
     168     1755129 :         *length = 1;
     169             :     }
     170    12688964 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_1_MAX )
     171             :     {
     172    12688748 :         *length = 1;
     173             :     }
     174         216 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_2_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_2_MAX )
     175             :     {
     176          51 :         *length = 2;
     177             :     }
     178         165 :     else if ( frameDataLengthValue >= LC3PLUS_RTP_FDL_LENGTH_3_MIN && frameDataLengthValue <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
     179             :     {
     180         165 :         *length = 3;
     181             :     }
     182             :     else
     183             :     {
     184           0 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     185             :     }
     186             : 
     187    14444093 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     188             : }
     189             : 
     190             : 
     191     2030557 : 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     2030557 :     if ( NULL == dst )
     199             :     {
     200           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     201             :     }
     202             : 
     203     2030557 :     err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, frameDataLengthValue );
     204     2030557 :     if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
     205             :     {
     206           0 :         return err;
     207             :     }
     208     2030557 :     if ( 1 == frame_data_length_size )
     209             :     {
     210     2030545 :         *dst++ = frameDataLengthValue >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     211             :     }
     212          12 :     else if ( 2 == frame_data_length_size )
     213             :     {
     214           8 :         const int32_t frameDataLengthValueToWrite = frameDataLengthValue - LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     215           8 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     216           8 :         *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     217             :     }
     218           4 :     else if ( 3 == frame_data_length_size )
     219             :     {
     220           4 :         const int32_t frameDataLengthValueToWrite = frameDataLengthValue - ( 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE );
     221           4 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     222           4 :         *dst++ = LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     223           4 :         *dst = frameDataLengthValueToWrite >> 0 & LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     224             :     }
     225             : 
     226     2030557 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     227             : }
     228             : 
     229             : 
     230     1768833 : static int32_t s_get_size_from_fdl(
     231             :     const LC3PLUS_RTP_FDL fdl )
     232             : {
     233     1768833 :     if ( fdl >= LC3PLUS_RTP_FDL_LENGTH_1_MIN && fdl <= LC3PLUS_RTP_FDL_LENGTH_3_MAX )
     234             :     {
     235     1768833 :         return fdl;
     236             :     }
     237             : 
     238           0 :     return 0;
     239             : }
     240             : 
     241             : 
     242     1768833 : static bool s_fdl_is_magic_value(
     243             :     const LC3PLUS_RTP_FDL fdl )
     244             : {
     245     1768833 :     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     1768833 :     return false;
     251             : }
     252             : 
     253             : 
     254      500125 : 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      500125 :     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      500125 :         return true;
     261             :     }
     262             : 
     263           0 :     return false;
     264             : }
     265             : 
     266             : 
     267     2018234 : 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     2018234 :     if ( NULL == src || NULL == frame_data_length_value || remaining_capacity < 1 )
     276             :     {
     277           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     278             :     }
     279             : 
     280     2018234 :     if ( remaining_capacity > 2 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *( src + 1 ) )
     281             :     {
     282          76 :         *frame_data_length_value = *( src + 2 ) + 2 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     283             :     }
     284     2018158 :     else if ( remaining_capacity > 1 && LC3PLUS_RTP_FDL_EXTENSION_VALUE == *src )
     285             :     {
     286           9 :         *frame_data_length_value = *( src + 1 ) + 1 * LC3PLUS_RTP_FDL_EXTENSION_VALUE;
     287             :     }
     288     2018149 :     else if ( remaining_capacity > 0 )
     289             :     {
     290     2018149 :         *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     2018234 :     err = LC3PLUS_RTP_frame_data_length_get_size( &frame_data_length_size, *frame_data_length_value );
     299     2018234 :     if ( err != LC3PLUS_RTP_ERR_NO_ERROR )
     300             :     {
     301           0 :         return err;
     302             :     }
     303             : 
     304     2018234 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     305             : }
     306             : 
     307             : 
     308     1768833 : 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     1768833 :     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     1768833 :     *num_bytes_read = 0;
     324     1768833 :     receiver_ftd->fc = 0;
     325     1768833 :     receiver_ftd->fdi = 0;
     326     1768833 :     receiver_ftd->bwr = 0;
     327     1768833 :     receiver_ftd->h = 0;
     328     1768833 :     receiver_ftd->fc |= *p_read & LC3PLUS_RTP_FTD_FC_MASK;
     329     1768833 :     receiver_ftd->fdi |= ( *p_read & LC3PLUS_RTP_FTD_FDI_MASK );
     330     1768833 :     receiver_ftd->bwr |= ( *p_read & LC3PLUS_RTP_FTD_BWR_MASK );
     331     1768833 :     receiver_ftd->h |= ( *p_read & LC3PLUS_RTP_FTD_H_MASK );
     332     1768833 :     p_read++;
     333     1768833 :     *num_bytes_read = 1;
     334             : 
     335     1768833 :     err = s_frame_data_length_parse( &fdl, p_read, remaining_capacity - *num_bytes_read );
     336     1768833 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     337             :     {
     338           0 :         return err;
     339             :     }
     340     1768833 :     frame_data_block_size = s_get_size_from_fdl( fdl );
     341             : 
     342     1768833 :     receiver_ftd->frame_data_length = frame_data_block_size;
     343             :     int32_t length_field_size;
     344     1768833 :     err = LC3PLUS_RTP_frame_data_length_get_size( &length_field_size, receiver_ftd->frame_data_length );
     345     1768833 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     346             :     {
     347           0 :         return err;
     348             :     }
     349     1768833 :     *num_bytes_read += length_field_size;
     350             : 
     351     1768833 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     352             : }
     353             : 
     354             : 
     355             : /*-------------------------------------------------------------------------
     356             :  * LC3PLUS_RTP_payload_serialize()
     357             :  *
     358             :  *
     359             :  *------------------------------------------------------------------------*/
     360             : 
     361      250724 : 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      250724 :     uint8_t *p_write = serialized_buffer;
     371             :     uint32_t i;
     372      250724 :     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      250724 :     if ( NULL == serialized_buffer || NULL == packed_buffer_actual_size || NULL == sender_ftds )
     378             :     {
     379           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     380             :     }
     381             : 
     382      250724 :     *packed_buffer_actual_size = 0;
     383      250724 :     err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, fdl_request );
     384      250724 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     385             :     {
     386           0 :         return err;
     387             :     }
     388      250724 :     if ( !s_fdl_value_is_valid_request( fdl_request ) )
     389             :     {
     390           0 :         return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
     391             :     }
     392      250724 :     if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_request_length )
     393             :     {
     394           0 :         return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     395             :     }
     396      250724 :     err = s_frame_data_length_pack( fdl_request, p_write );
     397      250724 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     398             :     {
     399           0 :         return err;
     400             :     }
     401      250724 :     bytes_written += fdl_request_length;
     402      250724 :     p_write += bytes_written;
     403             : 
     404     2030557 :     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     1779833 :         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     1779833 :         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     1779833 :         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     1779833 :         *p_write = 0x00;
     421     1779833 :         *p_write |= LC3PLUS_RTP_FTD_FC_MASK & (uint8_t) sender_ftds[i].fc;
     422     1779833 :         *p_write |= LC3PLUS_RTP_FTD_FDI_MASK & (uint8_t) sender_ftds[i].fdi;
     423     1779833 :         *p_write |= LC3PLUS_RTP_FTD_BWR_MASK & (uint8_t) sender_ftds[i].bwr;
     424     1779833 :         *p_write |= LC3PLUS_RTP_FTD_H_MASK & (uint8_t) sender_ftds[i].h;
     425     1779833 :         p_write++;
     426     1779833 :         bytes_written += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
     427             : 
     428             :         int32_t fdl_length;
     429     1779833 :         err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_length, sender_ftds[i].frame_data_length );
     430     1779833 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     431             :         {
     432           0 :             return err;
     433             :         }
     434     1779833 :         if ( (int32_t) serialized_buffer_capacity < bytes_written + fdl_length )
     435             :         {
     436           0 :             return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     437             :         }
     438     1779833 :         err = s_frame_data_length_pack( sender_ftds[i].frame_data_length, p_write );
     439     1779833 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     440             :         {
     441           0 :             return err;
     442             :         }
     443     1779833 :         p_write += fdl_length;
     444     1779833 :         bytes_written += fdl_length;
     445             :     }
     446             : 
     447      250724 :     lc3plus_frame_size_sum = 0;
     448      250724 :     p_frame_data = serialized_buffer + bytes_written;
     449     2030557 :     for ( i = 0; i < sender_ftds_num; ++i )
     450             :     {
     451     1779833 :         sender_ftds[i].frame_data = p_frame_data;
     452     1779833 :         p_frame_data += sender_ftds[i].frame_data_length;
     453     1779833 :         lc3plus_frame_size_sum += sender_ftds[i].frame_data_length;
     454             :     }
     455      250724 :     *packed_buffer_actual_size = bytes_written + lc3plus_frame_size_sum;
     456      250724 :     assert( *packed_buffer_actual_size <= serialized_buffer_capacity );
     457             : 
     458      250724 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     459             : }
     460             : 
     461             : 
     462      249401 : 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      249401 :     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      249401 :     p_read = serialized_buffer;
     478      249401 :     if ( NULL == receiver_ftds || NULL == receiver_ftds_num || NULL == serialized_buffer )
     479             :     {
     480           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     481             :     }
     482      249401 :     if ( 0 == serialized_buffer_size )
     483             :     {
     484           1 :         return LC3PLUS_RTP_ERR_EMPTY_TOC;
     485             :     }
     486      249400 :     if ( receiver_ftds_num_max <= 0 )
     487             :     {
     488           0 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     489             :     }
     490             : 
     491             :     {
     492      249400 :         int32_t num_bytes_read_sum = 0;
     493      249400 :         const int32_t min_num_bytes_per_ftd = 2;
     494      249400 :         int16_t receiver_ftds_index = 0;
     495      249400 :         bool another_ftd = true;
     496             :         int32_t num_bytes_read_per_ftd;
     497             : 
     498     2018233 :         while ( another_ftd )
     499             :         {
     500     1768837 :             if ( (int32_t) serialized_buffer_size < min_num_bytes_per_ftd )
     501             :             {
     502           4 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     503             :             }
     504     1768834 :             if ( num_bytes_read_sum >= (int32_t) serialized_buffer_size - min_num_bytes_per_ftd )
     505             :             {
     506           1 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     507             :             }
     508     1768833 :             num_bytes_read_per_ftd = 0;
     509     1768833 :             error = s_parse_ftd( p_read, &receiver_ftds[receiver_ftds_index], &num_bytes_read_per_ftd, serialized_buffer_size - num_bytes_read_sum );
     510     1768833 :             if ( LC3PLUS_RTP_ERR_NO_ERROR != error )
     511             :             {
     512           0 :                 return error;
     513             :             }
     514     1768833 :             p_read += num_bytes_read_per_ftd;
     515     1768833 :             num_bytes_read_sum += num_bytes_read_per_ftd;
     516             : 
     517     1768833 :             if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_RESERVED )
     518             :             {
     519           0 :                 return LC3PLUS_RTP_ERR_INVALID_BITSTREAM;
     520             :             }
     521     1768833 :             else if ( receiver_ftds[receiver_ftds_index].fc == LC3PLUS_RTP_FTD_FC_LAST_OVERALL )
     522             :             {
     523      249396 :                 another_ftd = false;
     524             :             }
     525             : 
     526     1768833 :             if ( another_ftd )
     527             :             {
     528     1519437 :                 if ( receiver_ftds_index >= receiver_ftds_num_max )
     529             :                 {
     530           0 :                     return LC3PLUS_RTP_ERR_NOT_ENOUGH_FTDS_ALLOCATED;
     531             :                 }
     532     1519437 :                 ( receiver_ftds_index )++;
     533             :             }
     534             :         }
     535      249396 :         *receiver_ftds_num = receiver_ftds_index + 1;
     536             :     }
     537             : 
     538             :     /* set frame-data pointers into serialized_buffer */
     539     2018229 :     for ( i = 0; i < *receiver_ftds_num; ++i )
     540             :     {
     541     1768833 :         error = LC3PLUS_RTP_frame_data_length_get_size( &size, receiver_ftds[i].frame_data_length );
     542     1768833 :         if ( error != LC3PLUS_RTP_ERR_NO_ERROR )
     543             :         {
     544           0 :             return error;
     545             :         }
     546     1768833 :         ftds_offset_sum += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL + size;
     547             :     }
     548             : 
     549      249396 :     frame_offset_counter = 0;
     550     2018229 :     for ( i = 0; i < *receiver_ftds_num; ++i )
     551             :     {
     552     1768833 :         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     1768833 :             receiver_ftds[i].frame_data = serialized_buffer + ftds_offset_sum + frame_offset_counter;
     559     1768833 :             frame_offset_counter += receiver_ftds[i].frame_data_length;
     560             :         }
     561             :     }
     562             : 
     563      249396 :     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      236914 :         diff = serialized_buffer_size - ( ftds_offset_sum + frame_offset_counter );
     568      236914 :         if ( diff < 0 )
     569             :         {
     570          69 :             return LC3PLUS_RTP_ERR_INVALID_BITSTREAM_SIZE;
     571             :         }
     572             :         /* verify that all bytes are zero */
     573      236845 :         p_read += frame_offset_counter;
     574    14031090 :         for ( i = 0; i < diff; ++i )
     575             :         {
     576    13794245 :             if ( *p_read != 0 )
     577             :             {
     578             :                 /* non-zero byte in padding region */
     579           0 :                 return LC3PLUS_RTP_ERR_NONZERO_PADDING_BYTES;
     580             :             }
     581    13794245 :             p_read++;
     582             :         }
     583             :     }
     584             : 
     585      249327 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     586             : }
     587             : 
     588             : 
     589             : /*-------------------------------------------------------------------------
     590             :  * LC3PLUS_RTP_payload_deserialize()
     591             :  *
     592             :  *
     593             :  *------------------------------------------------------------------------*/
     594             : 
     595      249402 : 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      249402 :     int16_t i = 0;
     604      249402 :     int16_t channel_id = 0;
     605      249402 :     int16_t media_time_id = 0;
     606      249402 :     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      249402 :     if ( NULL == payload || NULL == serialized_buffer )
     612             :     {
     613           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     614             :     }
     615      249402 :     if ( 0 == serialized_buffer_size )
     616             :     {
     617           1 :         return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     618             :     }
     619             : 
     620     2244609 :     for ( media_time_id = 0; media_time_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++media_time_id )
     621             :     {
     622     1995208 :         channels_per_media_time[media_time_id] = invalid_value;
     623             :     }
     624      249401 :     media_time_id = 0;
     625     4239817 :     for ( channel_id = 0; channel_id < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++channel_id )
     626             :     {
     627     3990416 :         media_times_per_channel[channel_id] = invalid_value;
     628             :     }
     629      249401 :     channel_id = 0;
     630             : 
     631      249401 :     err = s_frame_data_length_parse( &payload->fdl_request, serialized_buffer, serialized_buffer_size );
     632      249401 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     633             :     {
     634           0 :         return err;
     635             :     }
     636             :     int32_t fdl_request_length;
     637      249401 :     err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, payload->fdl_request );
     638      249401 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     639             :     {
     640           0 :         return err;
     641             :     }
     642      249401 :     if ( !s_fdl_value_is_valid_request( payload->fdl_request ) )
     643             :     {
     644           0 :         return LC3PLUS_RTP_ERR_INVALID_FDL_REQUEST;
     645             :     }
     646             : 
     647      249401 :     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      249401 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     649             :     {
     650          74 :         return err;
     651             :     }
     652      249327 :     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      249327 :     err = s_frame_duration_ms_from_fdi( &payload->frame_duration_us, payload->ftds[0].fdi );
     660      249327 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     661             :     {
     662           0 :         return err;
     663             :     }
     664      249327 :     err = s_sampling_rate_hz_from_bwr( &payload->sampling_rate_hz, payload->ftds[0].bwr );
     665      249327 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     666             :     {
     667           0 :         return err;
     668             :     }
     669      249327 :     err = s_high_resolution_flag_from_bwr( &payload->high_resolution_enabled, payload->ftds[0].bwr );
     670      249327 :     if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     671             :     {
     672           0 :         return err;
     673             :     }
     674      249327 :     payload->num_channels = 0;
     675      249327 :     payload->num_media_times = 0;
     676     2018091 :     for ( i = 0; i < payload->num_ftds; ++i )
     677             :     {
     678     1768764 :         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     1768764 :         err = s_frame_duration_ms_from_fdi( &new_frame_duration_us, payload->ftds[i].fdi );
     685     1768764 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     686             :         {
     687           0 :             return err;
     688             :         }
     689     1768764 :         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     1768764 :         err = s_sampling_rate_hz_from_bwr( &new_sampling_rate_hz, payload->ftds[i].bwr );
     696     1768764 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     697             :         {
     698           0 :             return err;
     699             :         }
     700     1768764 :         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     1768764 :         err = s_high_resolution_flag_from_bwr( &new_high_resolution_flag, payload->ftds[i].bwr );
     708     1768764 :         if ( LC3PLUS_RTP_ERR_NO_ERROR != err )
     709             :         {
     710           0 :             return err;
     711             :         }
     712     1768764 :         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     1768764 :         switch ( payload->ftds[i].fc )
     719             :         {
     720      249327 :             case LC3PLUS_RTP_FTD_FC_LAST_OVERALL:
     721      249327 :                 channels_per_media_time[media_time_id]++;
     722      249327 :                 media_times_per_channel[channel_id]++;
     723      249327 :                 channel_id = 0;
     724      249327 :                 media_time_id = 0;
     725      249327 :                 break;
     726      884376 :             case LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL:
     727      884376 :                 media_times_per_channel[channel_id]++;
     728      884376 :                 channels_per_media_time[media_time_id]++;
     729      884376 :                 channel_id++;
     730      884376 :                 break;
     731      635061 :             case LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME:
     732      635061 :                 media_times_per_channel[channel_id]++;
     733      635061 :                 channels_per_media_time[media_time_id]++;
     734      635061 :                 channel_id = 0;
     735      635061 :                 media_time_id++;
     736      635061 :                 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      249327 :         if ( media_times_per_channel[0] == invalid_value )
     748             :         {
     749           0 :             return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     750             :         }
     751      249327 :         valid_num_media_times_per_channel = media_times_per_channel[0];
     752      747970 :         for ( iCh = 0; iCh < LC3PLUS_RTP_PAYLOAD_MAX_NUM_CHANNELS; ++iCh )
     753             :         {
     754      747970 :             if ( media_times_per_channel[iCh] == invalid_value )
     755             :             {
     756      249327 :                 break;
     757             :             }
     758      498643 :             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      249327 :         if ( channels_per_media_time[0] == invalid_value )
     769             :         {
     770           0 :             return LC3PLUS_RTP_ERR_NOT_IMPLEMENTED;
     771             :         }
     772      249327 :         valid_num_channels_per_media_time = channels_per_media_time[0];
     773     1133715 :         for ( iMediaTime = 0; iMediaTime < LC3PLUS_RTP_PAYLOAD_MAX_NUM_MEDIA_TIMES; ++iMediaTime )
     774             :         {
     775     1133714 :             if ( channels_per_media_time[iMediaTime] == invalid_value )
     776             :             {
     777      249326 :                 break;
     778             :             }
     779      884388 :             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      249327 :     payload->num_channels = channels_per_media_time[0] + 1;
     788      249327 :     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      249327 :     if ( payload->num_ftds != payload->num_channels * payload->num_media_times )
     792             :     {
     793           0 :         return LC3PLUS_RTP_ERR_GENERIC_ERROR;
     794             :     }
     795             : 
     796      249327 :     return LC3PLUS_RTP_ERR_NO_ERROR;
     797             : }
     798             : 
     799             : 
     800             : /*-------------------------------------------------------------------------
     801             :  * LC3PLUS_RTP_ftd_bwr_from_samplerate()
     802             :  *
     803             :  *
     804             :  *------------------------------------------------------------------------*/
     805             : 
     806       10888 : 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       10888 :     if ( NULL == bwr )
     812             :     {
     813           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     814             :     }
     815       10888 :     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           4 :         case 16000:
     825           4 :             if ( high_res_enabled )
     826             :             {
     827           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     828             :             }
     829           4 :             *bwr = LC3PLUS_RTP_FTD_BWR_WB;
     830           4 :             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           4 :         case 32000:
     839           4 :             if ( high_res_enabled )
     840             :             {
     841           0 :                 return LC3PLUS_RTP_ERR_INVALID_PARAMETERS;
     842             :             }
     843           4 :             *bwr = LC3PLUS_RTP_FTD_BWR_SWB;
     844           4 :             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       10880 :         case 48000:
     853       10880 :             if ( 0 == high_res_enabled )
     854             :             {
     855       10880 :                 *bwr = LC3PLUS_RTP_FTD_BWR_FB;
     856       10880 :                 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       10888 : 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       10888 :     if ( NULL == fdi )
     889             :     {
     890           0 :         return LC3PLUS_RTP_ERR_NULL_PTR;
     891             :     }
     892       10888 :     switch ( frame_duration_us )
     893             :     {
     894          16 :         case 2500:
     895          16 :             *fdi = LC3PLUS_RTP_FTD_FDI_2500_US;
     896          16 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     897       10452 :         case 5000:
     898       10452 :             *fdi = LC3PLUS_RTP_FTD_FDI_5000_US;
     899       10452 :             return LC3PLUS_RTP_ERR_NO_ERROR;
     900         420 :         case 10000:
     901         420 :             *fdi = LC3PLUS_RTP_FTD_FDI_10000_US;
     902         420 :             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