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
|