LCOV - code coverage report
Current view: top level - lib_dec - jbm_jb4_inputbuffer.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 8834b716eb6d7dfb881d5c69dd21cb18e1692722 Lines: 74 115 64.3 %
Date: 2025-07-09 08:36:12 Functions: 11 11 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             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : /** \file jbm_jb4_inputbuffer.c RTP input buffer with fixed capacity. */
      38             : 
      39             : #include <assert.h>
      40             : #include <stdint.h>
      41             : #include "options.h"
      42             : #include "prot.h"
      43             : #include "string.h"
      44             : #ifdef DEBUGGING
      45             : #include "debug.h"
      46             : #endif
      47             : #include "jbm_jb4_inputbuffer.h"
      48             : #include "wmc_auto.h"
      49             : 
      50             : #define WMC_TOOL_SKIP
      51             : 
      52             : 
      53             : /** input buffer with fixed capacity */
      54             : struct JB4_INPUTBUFFER
      55             : {
      56             :     /** elements of input buffer */
      57             :     JB4_INPUTBUFFER_ELEMENT *data;
      58             :     /** maximum allowed number of elements plus one free element (to decide between full/empty buffer) */
      59             :     uint16_t capacity;
      60             :     /** position of next enque operation */
      61             :     uint16_t writePos;
      62             :     /** position of next deque operation */
      63             :     uint16_t readPos;
      64             :     /** function to compare two elements */
      65             :     int16_t ( *compareFunction )( const JB4_INPUTBUFFER_ELEMENT first, const JB4_INPUTBUFFER_ELEMENT second, bool *replaceWithNewElementIfEqual );
      66             : };
      67             : 
      68             : 
      69             : /* Creates a input buffer */
      70         105 : ivas_error JB4_INPUTBUFFER_Create(
      71             :     JB4_INPUTBUFFER_HANDLE *ph )
      72             : {
      73             :     JB4_INPUTBUFFER_HANDLE h;
      74             : 
      75         105 :     if ( ( h = malloc( sizeof( struct JB4_INPUTBUFFER ) ) ) == NULL )
      76             :     {
      77           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) );
      78             :     }
      79             : 
      80         105 :     h->data = NULL;
      81         105 :     h->capacity = 0;
      82         105 :     h->writePos = 0;
      83         105 :     h->readPos = 0;
      84         105 :     h->compareFunction = NULL;
      85             : 
      86         105 :     *ph = h;
      87             : 
      88         105 :     return IVAS_ERR_OK;
      89             : }
      90             : 
      91             : 
      92             : /* Destroys the input buffer */
      93         105 : void JB4_INPUTBUFFER_Destroy(
      94             :     JB4_INPUTBUFFER_HANDLE *ph )
      95             : {
      96             :     JB4_INPUTBUFFER_HANDLE h;
      97             : 
      98         105 :     if ( !ph )
      99             :     {
     100           0 :         return;
     101             :     }
     102         105 :     h = *ph;
     103         105 :     if ( !h )
     104             :     {
     105           0 :         return;
     106             :     }
     107             : 
     108         105 :     if ( h->data )
     109             :     {
     110         105 :         free( h->data );
     111             :     }
     112             : 
     113         105 :     free( h );
     114         105 :     *ph = NULL;
     115             : 
     116         105 :     return;
     117             : }
     118             : 
     119             : 
     120             : /* Initializes a input buffer with a fixed maximum allowed number of elements */
     121         105 : ivas_error JB4_INPUTBUFFER_Init(
     122             :     JB4_INPUTBUFFER_HANDLE h,
     123             :     uint16_t capacity,
     124             :     int16_t ( *compareFunction )( const JB4_INPUTBUFFER_ELEMENT first, const JB4_INPUTBUFFER_ELEMENT second, bool *replaceWithNewElementIfEqual ) )
     125             : {
     126             : 
     127             :     /* keep one element free to be able to decide between full/empty buffer */
     128         105 :     ++capacity;
     129         105 :     if ( ( h->data = malloc( capacity * sizeof( JB4_INPUTBUFFER_ELEMENT ) ) ) == NULL )
     130             :     {
     131           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for JBM\n" ) );
     132             :     }
     133             : 
     134         105 :     h->capacity = capacity;
     135         105 :     h->writePos = 0;
     136         105 :     h->readPos = 0;
     137         105 :     h->compareFunction = compareFunction;
     138             : 
     139         105 :     return IVAS_ERR_OK;
     140             : }
     141             : 
     142             : 
     143       69921 : int16_t JB4_INPUTBUFFER_Enque(
     144             :     JB4_INPUTBUFFER_HANDLE h,
     145             :     JB4_INPUTBUFFER_ELEMENT element,
     146             :     JB4_INPUTBUFFER_ELEMENT *replacedElement )
     147             : {
     148             :     uint16_t j, size;
     149             :     int16_t low, high, middle, diff;
     150             :     uint16_t insertPos;
     151             :     uint16_t canMoveRight;
     152             :     uint16_t canMoveLeft;
     153             :     bool replace;
     154             : 
     155       69921 :     *replacedElement = NULL;
     156             : 
     157       69921 :     size = JB4_INPUTBUFFER_Size( h );
     158       69921 :     if ( size >= h->capacity - 1 )
     159             :     {
     160           0 :         return -1;
     161             :     }
     162             : 
     163             :     /* appending the first element is straight forward */
     164       69921 :     if ( size == 0U )
     165             :     {
     166        2025 :         h->data[h->writePos] = element;
     167        2025 :         ++h->writePos;
     168        2025 :         if ( h->writePos == h->capacity )
     169             :         {
     170           3 :             h->writePos = 0;
     171             :         }
     172        2025 :         return 0;
     173             :     }
     174             : 
     175             :     /* there's a high probability that the new element can be appended at the back */
     176       67896 :     if ( h->compareFunction( element, JB4_INPUTBUFFER_Back( h ), &replace ) > 0 )
     177             :     {
     178       67896 :         h->data[h->writePos] = element;
     179       67896 :         ++h->writePos;
     180       67896 :         if ( h->writePos == h->capacity )
     181             :         {
     182         648 :             h->writePos = 0;
     183             :         }
     184       67896 :         return 0;
     185             :     }
     186             : 
     187             :     /* out of order: use binary search to get the position to insert */
     188           0 :     low = 0;
     189           0 :     high = size - 1;
     190           0 :     while ( low <= high )
     191             :     {
     192           0 :         middle = low + ( high - low ) / 2;
     193           0 :         diff = h->compareFunction( element, JB4_INPUTBUFFER_Element( h, middle ), &replace );
     194           0 :         if ( diff < 0 )
     195             :         {
     196           0 :             high = middle - 1;
     197             :         }
     198           0 :         else if ( diff > 0 )
     199             :         {
     200           0 :             low = middle + 1;
     201             :         }
     202             :         else /* an element with same index is already stored */
     203             :         {
     204           0 :             if ( replace != 0 )
     205             :             {
     206           0 :                 *replacedElement = h->data[( h->readPos + middle ) % h->capacity];
     207           0 :                 h->data[( h->readPos + middle ) % h->capacity] = element;
     208           0 :                 return 0;
     209             :             }
     210           0 :             return 1;
     211             :         }
     212             :     }
     213             : 
     214             : #ifdef DEBUGGING
     215             :     assert( h->compareFunction( element, JB4_INPUTBUFFER_Element( h, low ), &replace ) != 0 );
     216             :     if ( low > 0 )
     217             :         assert( h->compareFunction( element, JB4_INPUTBUFFER_Element( h, low - 1 ), &replace ) > 0 );
     218             :     assert( h->compareFunction( element, JB4_INPUTBUFFER_Element( h, low ), &replace ) < 0 );
     219             :     if ( (uint16_t) ( low + 1 ) < size )
     220             :         assert( h->compareFunction( element, JB4_INPUTBUFFER_Element( h, low + 1 ), &replace ) < 0 );
     221             : #endif
     222             : 
     223           0 :     insertPos = ( h->readPos + low ) % h->capacity;
     224           0 :     if ( h->readPos < h->writePos )
     225             :     {
     226           0 :         canMoveRight = 1;
     227           0 :         canMoveLeft = h->readPos > 0;
     228             :     }
     229             :     else
     230             :     {
     231           0 :         canMoveRight = insertPos < h->writePos;
     232           0 :         canMoveLeft = insertPos > h->writePos;
     233             :     }
     234             : 
     235           0 :     assert( canMoveRight != 0 || canMoveLeft != 0 );
     236             : 
     237           0 :     if ( canMoveRight )
     238             :     {
     239             :         /* move higher elements to the right and insert at insertPos */
     240           0 :         for ( j = h->writePos; j > insertPos; --j )
     241             :         {
     242           0 :             h->data[j] = h->data[j - 1];
     243             :         }
     244             : 
     245           0 :         h->data[insertPos] = element;
     246           0 :         ++h->writePos;
     247           0 :         if ( h->writePos == h->capacity )
     248             :         {
     249           0 :             h->writePos = 0;
     250             :         }
     251             :     }
     252             :     else
     253             :     {
     254             :         /* move lower elements to the left and insert before insertPos */
     255           0 :         for ( j = 0; j < low; j++ )
     256             :         {
     257           0 :             h->data[h->readPos - 1 + j] = h->data[h->readPos + j];
     258             :         }
     259             : 
     260           0 :         h->data[insertPos - 1] = element;
     261           0 :         --h->readPos;
     262           0 :         assert( (int16_t) h->readPos >= 0 );
     263             :     }
     264             : 
     265           0 :     return 0;
     266             : }
     267             : 
     268             : 
     269       69921 : int16_t JB4_INPUTBUFFER_Deque(
     270             :     JB4_INPUTBUFFER_HANDLE h,
     271             :     JB4_INPUTBUFFER_ELEMENT *pElement )
     272             : {
     273       69921 :     if ( JB4_INPUTBUFFER_IsEmpty( h ) )
     274             :     {
     275           0 :         return -1;
     276             :     }
     277             : 
     278       69921 :     *pElement = h->data[h->readPos];
     279       69921 :     ++h->readPos;
     280       69921 :     if ( h->readPos == h->capacity )
     281             :     {
     282         651 :         h->readPos = 0;
     283             :     }
     284             : 
     285       69921 :     return 0;
     286             : }
     287             : 
     288             : 
     289             : /* Returns the first element. */
     290      151059 : JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Front(
     291             :     const JB4_INPUTBUFFER_HANDLE h )
     292             : {
     293             :     JB4_INPUTBUFFER_ELEMENT ret;
     294             : 
     295             : 
     296      151059 :     ret = h->data[h->readPos];
     297             : 
     298      151059 :     return ret;
     299             : }
     300             : 
     301             : 
     302             : /* Returns the last element. */
     303       69048 : JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Back(
     304             :     const JB4_INPUTBUFFER_HANDLE h )
     305             : {
     306             :     JB4_INPUTBUFFER_ELEMENT ret;
     307             : 
     308       69048 :     if ( h->writePos != 0U )
     309             :     {
     310       68442 :         ret = h->data[h->writePos - 1];
     311             :     }
     312             :     else
     313             :     {
     314         606 :         ret = h->data[h->capacity - 1];
     315             :     }
     316             : 
     317       69048 :     return ret;
     318             : }
     319             : 
     320             : 
     321             : /* Returns the element with the given index (0 means front element). */
     322       18462 : JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Element(
     323             :     const JB4_INPUTBUFFER_HANDLE h,
     324             :     uint16_t index )
     325             : {
     326             :     JB4_INPUTBUFFER_ELEMENT ret;
     327             : 
     328             :     /* return h->data[(h->readPos + index) % h->capacity] without error handling */
     329       18462 :     if ( h->readPos + index < h->capacity )
     330             :     {
     331       18411 :         ret = h->data[h->readPos + index];
     332             :     }
     333             :     else
     334             :     {
     335             :         /* wrap around */
     336          51 :         ret = h->data[h->readPos + index - h->capacity];
     337             :     }
     338             : 
     339       18462 :     return ret;
     340             : }
     341             : 
     342             : 
     343      224010 : int16_t JB4_INPUTBUFFER_IsEmpty(
     344             :     const JB4_INPUTBUFFER_HANDLE h )
     345             : {
     346             :     int16_t ret;
     347             : 
     348      224010 :     ret = h->readPos == h->writePos;
     349             : 
     350      224010 :     return ret;
     351             : }
     352             : 
     353             : 
     354      139842 : int16_t JB4_INPUTBUFFER_IsFull(
     355             :     const JB4_INPUTBUFFER_HANDLE h )
     356             : {
     357             :     int16_t ret;
     358             : 
     359      139842 :     ret = 0;
     360      139842 :     if ( JB4_INPUTBUFFER_Size( h ) == h->capacity - 1 )
     361             :     {
     362           0 :         ret = 1;
     363             :     }
     364             : 
     365      139842 :     return ret;
     366             : }
     367             : 
     368             : 
     369      217472 : uint16_t JB4_INPUTBUFFER_Size(
     370             :     const JB4_INPUTBUFFER_HANDLE h )
     371             : {
     372             :     uint16_t ret;
     373             : 
     374      217472 :     if ( h->readPos <= h->writePos )
     375             :     {
     376      208640 :         ret = h->writePos - h->readPos;
     377             :     }
     378             :     else
     379             :     {
     380             :         /* wrap around */
     381        8832 :         ret = h->writePos + h->capacity - h->readPos;
     382             :     }
     383             : 
     384      217472 :     return ret;
     385             : }
     386             : 
     387             : #undef WMC_TOOL_SKIP

Generated by: LCOV version 1.14