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