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

Generated by: LCOV version 1.14