diff options
Diffstat (limited to 'toxrtp/toxrtp.c')
-rw-r--r-- | toxrtp/toxrtp.c | 693 |
1 files changed, 0 insertions, 693 deletions
diff --git a/toxrtp/toxrtp.c b/toxrtp/toxrtp.c deleted file mode 100644 index 6844b0b1..00000000 --- a/toxrtp/toxrtp.c +++ /dev/null | |||
@@ -1,693 +0,0 @@ | |||
1 | /* rtp_impl.c | ||
2 | * | ||
3 | * Rtp implementation includes rtp_session_s struct which is a session identifier. | ||
4 | * It contains session information and it's a must for every session. | ||
5 | * It's best if you don't touch any variable directly but use callbacks to do so. !Red! | ||
6 | * | ||
7 | * | ||
8 | * Copyright (C) 2013 Tox project All Rights Reserved. | ||
9 | * | ||
10 | * This file is part of Tox. | ||
11 | * | ||
12 | * Tox is free software: you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation, either version 3 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * Tox is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with Tox. If not, see <http://www.gnu.org/licenses/>. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #ifdef HAVE_CONFIG_H | ||
28 | #include "config.h" | ||
29 | #endif /* HAVE_CONFIG_H */ | ||
30 | |||
31 | #include "toxrtp.h" | ||
32 | #include "toxrtp_message.h" | ||
33 | #include "toxrtp_helper.h" | ||
34 | #include <assert.h> | ||
35 | #include <pthread.h> | ||
36 | #include "../toxcore/util.h" | ||
37 | #include "../toxcore/network.h" | ||
38 | |||
39 | /* Some defines */ | ||
40 | #define PAYLOAD_ID_VALUE_OPUS 1 | ||
41 | #define PAYLOAD_ID_VALUE_VP8 2 | ||
42 | |||
43 | #define size_32 4 | ||
44 | /* End of defines */ | ||
45 | |||
46 | #ifdef _USE_ERRORS | ||
47 | #include "toxrtp_error_id.h" | ||
48 | #endif /* _USE_ERRORS */ | ||
49 | |||
50 | static const uint32_t _payload_table[] = /* PAYLOAD TABLE */ | ||
51 | { | ||
52 | 8000, 8000, 8000, 8000, 8000, 8000, 16000, 8000, 8000, 8000, /* 0-9 */ | ||
53 | 44100, 44100, 0, 0, 90000, 8000, 11025, 22050, 0, 0, /* 10-19 */ | ||
54 | 0, 0, 0, 0, 0, 90000, 90000, 0, 90000, 0, /* 20-29 */ | ||
55 | 0, 90000, 90000, 90000, 90000, 0, 0, 0, 0, 0, /* 30-39 */ | ||
56 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40-49 */ | ||
57 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50-59 */ | ||
58 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60-69 */ | ||
59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70-79 */ | ||
60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80-89 */ | ||
61 | 0, 0, 0, 0, 0, 0, PAYLOAD_ID_VALUE_OPUS, 0, 0, 0, /* 90-99 */ | ||
62 | 0, 0, 0, 0, 0, 0, PAYLOAD_ID_VALUE_VP8, 0, 0, 0, /* 100-109 */ | ||
63 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 110-119 */ | ||
64 | 0, 0, 0, 0, 0, 0, 0, 0 /* 120-127 */ | ||
65 | }; | ||
66 | |||
67 | /* Current compatibility solution */ | ||
68 | int m_sendpacket(Networking_Core* _core_handler, void *ip_port, uint8_t *data, uint32_t length) | ||
69 | { | ||
70 | return sendpacket(_core_handler, *((IP_Port*) ip_port), data, length); | ||
71 | } | ||
72 | |||
73 | rtp_session_t* rtp_init_session ( int max_users, int _multi_session ) | ||
74 | { | ||
75 | #ifdef _USE_ERRORS | ||
76 | REGISTER_RTP_ERRORS | ||
77 | #endif /* _USE_ERRORS */ | ||
78 | |||
79 | rtp_session_t* _retu = calloc(sizeof(rtp_session_t), 1); | ||
80 | assert(_retu); | ||
81 | |||
82 | _retu->_dest_list = _retu->_last_user = NULL; | ||
83 | |||
84 | _retu->_max_users = max_users; | ||
85 | _retu->_packets_recv = 0; | ||
86 | _retu->_packets_sent = 0; | ||
87 | _retu->_bytes_sent = 0; | ||
88 | _retu->_bytes_recv = 0; | ||
89 | _retu->_last_error = NULL; | ||
90 | _retu->_packet_loss = 0; | ||
91 | |||
92 | /* | ||
93 | * SET HEADER FIELDS | ||
94 | */ | ||
95 | |||
96 | _retu->_version = RTP_VERSION; /* It's always 2 */ | ||
97 | _retu->_padding = 0; /* If some additional data is needed about | ||
98 | * the packet */ | ||
99 | _retu->_extension = 0; /* If extension to header is needed */ | ||
100 | _retu->_cc = 1; /* It basically represents amount of contributors */ | ||
101 | _retu->_csrc = NULL; /* Container */ | ||
102 | _retu->_ssrc = t_random ( -1 ); | ||
103 | _retu->_marker = 0; | ||
104 | _retu->_payload_type = 0; /* You should specify payload type */ | ||
105 | |||
106 | /* Sequence starts at random number and goes to _MAX_SEQU_NUM */ | ||
107 | _retu->_sequence_number = t_random ( _MAX_SEQU_NUM ); | ||
108 | _retu->_last_sequence_number = _retu->_sequence_number; /* Do not touch this variable */ | ||
109 | |||
110 | _retu->_initial_time = t_time(); /* In seconds */ | ||
111 | assert(_retu->_initial_time); | ||
112 | _retu->_time_elapsed = 0; /* In seconds */ | ||
113 | |||
114 | _retu->_ext_header = NULL; /* When needed allocate */ | ||
115 | _retu->_exthdr_framerate = -1; | ||
116 | _retu->_exthdr_resolution = -1; | ||
117 | |||
118 | _retu->_csrc = calloc(sizeof(uint32_t), 1); | ||
119 | assert(_retu->_csrc); | ||
120 | |||
121 | _retu->_csrc[0] = _retu->_ssrc; /* Set my ssrc to the list receive */ | ||
122 | |||
123 | _retu->_prefix_length = 0; | ||
124 | _retu->_prefix = NULL; | ||
125 | |||
126 | _retu->_multi_session = _multi_session; | ||
127 | |||
128 | /* Initial */ | ||
129 | _retu->_current_framerate = 0; | ||
130 | |||
131 | |||
132 | _retu->_oldest_msg = _retu->_last_msg = NULL; | ||
133 | |||
134 | pthread_mutex_init(&_retu->_mutex, NULL); | ||
135 | /* | ||
136 | * | ||
137 | */ | ||
138 | return _retu; | ||
139 | } | ||
140 | |||
141 | int rtp_terminate_session ( rtp_session_t* _session ) | ||
142 | { | ||
143 | if ( !_session ) | ||
144 | return FAILURE; | ||
145 | |||
146 | if ( _session->_dest_list ){ | ||
147 | rtp_dest_list_t* _fordel = NULL; | ||
148 | rtp_dest_list_t* _tmp = _session->_dest_list; | ||
149 | |||
150 | while( _tmp ){ | ||
151 | _fordel = _tmp; | ||
152 | _tmp = _tmp->next; | ||
153 | free(_fordel); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | if ( _session->_ext_header ) | ||
158 | free ( _session->_ext_header ); | ||
159 | |||
160 | if ( _session->_csrc ) | ||
161 | free ( _session->_csrc ); | ||
162 | |||
163 | if ( _session->_prefix ) | ||
164 | free ( _session->_prefix ); | ||
165 | |||
166 | pthread_mutex_destroy(&_session->_mutex); | ||
167 | |||
168 | /* And finally free session */ | ||
169 | free ( _session ); | ||
170 | |||
171 | return SUCCESS; | ||
172 | } | ||
173 | |||
174 | uint16_t rtp_get_resolution_marking_height ( rtp_ext_header_t* _header, uint32_t _position ) | ||
175 | { | ||
176 | if ( _header->_ext_type & RTP_EXT_TYPE_RESOLUTION ) | ||
177 | return _header->_hd_ext[_position]; | ||
178 | else | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | uint16_t rtp_get_resolution_marking_width ( rtp_ext_header_t* _header, uint32_t _position ) | ||
183 | { | ||
184 | if ( _header->_ext_type & RTP_EXT_TYPE_RESOLUTION ) | ||
185 | return ( _header->_hd_ext[_position] >> 16 ); | ||
186 | else | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | void rtp_free_msg ( rtp_session_t* _session, rtp_msg_t* _message ) | ||
191 | { | ||
192 | free ( _message->_data ); | ||
193 | |||
194 | if ( !_session ){ | ||
195 | free ( _message->_header->_csrc ); | ||
196 | if ( _message->_ext_header ){ | ||
197 | free ( _message->_ext_header->_hd_ext ); | ||
198 | free ( _message->_ext_header ); | ||
199 | } | ||
200 | } else { | ||
201 | if ( _session->_csrc != _message->_header->_csrc ) | ||
202 | free ( _message->_header->_csrc ); | ||
203 | if ( _message->_ext_header && _session->_ext_header != _message->_ext_header ) { | ||
204 | free ( _message->_ext_header->_hd_ext ); | ||
205 | free ( _message->_ext_header ); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | free ( _message->_header ); | ||
210 | free ( _message ); | ||
211 | } | ||
212 | |||
213 | rtp_header_t* rtp_build_header ( rtp_session_t* _session ) | ||
214 | { | ||
215 | rtp_header_t* _retu; | ||
216 | _retu = calloc ( sizeof * _retu, 1 ); | ||
217 | assert(_retu); | ||
218 | |||
219 | rtp_header_add_flag_version ( _retu, _session->_version ); | ||
220 | rtp_header_add_flag_padding ( _retu, _session->_padding ); | ||
221 | rtp_header_add_flag_extension ( _retu, _session->_extension ); | ||
222 | rtp_header_add_flag_CSRC_count ( _retu, _session->_cc ); | ||
223 | rtp_header_add_setting_marker ( _retu, _session->_marker ); | ||
224 | rtp_header_add_setting_payload ( _retu, _session->_payload_type ); | ||
225 | |||
226 | _retu->_sequence_number = _session->_sequence_number; | ||
227 | _session->_time_elapsed = t_time() - _session->_initial_time; | ||
228 | _retu->_timestamp = t_time(); | ||
229 | _retu->_ssrc = _session->_ssrc; | ||
230 | |||
231 | if ( _session->_cc > 0 ) { | ||
232 | _retu->_csrc = calloc(sizeof(uint32_t), _session->_cc); | ||
233 | assert(_retu->_csrc); | ||
234 | |||
235 | int i; | ||
236 | |||
237 | for ( i = 0; i < _session->_cc; i++ ) { | ||
238 | _retu->_csrc[i] = _session->_csrc[i]; | ||
239 | } | ||
240 | } else { | ||
241 | _retu->_csrc = NULL; | ||
242 | } | ||
243 | |||
244 | _retu->_length = _MIN_HEADER_LENGTH + ( _session->_cc * size_32 ); | ||
245 | |||
246 | return _retu; | ||
247 | } | ||
248 | |||
249 | void rtp_set_payload_type ( rtp_session_t* _session, uint8_t _payload_value ) | ||
250 | { | ||
251 | _session->_payload_type = _payload_value; | ||
252 | } | ||
253 | uint32_t rtp_get_payload_type ( rtp_session_t* _session ) | ||
254 | { | ||
255 | return _payload_table[_session->_payload_type]; | ||
256 | } | ||
257 | |||
258 | int rtp_add_receiver ( rtp_session_t* _session, tox_IP_Port* _dest ) | ||
259 | { | ||
260 | if ( !_session ) | ||
261 | return FAILURE; | ||
262 | |||
263 | rtp_dest_list_t* _new_user = calloc(sizeof(rtp_dest_list_t), 1); | ||
264 | assert(_new_user); | ||
265 | |||
266 | _new_user->next = NULL; | ||
267 | _new_user->_dest = *_dest; | ||
268 | |||
269 | if ( _session->_last_user == NULL ) { /* New member */ | ||
270 | _session->_dest_list = _session->_last_user = _new_user; | ||
271 | |||
272 | } else { /* Append */ | ||
273 | _session->_last_user->next = _new_user; | ||
274 | _session->_last_user = _new_user; | ||
275 | } | ||
276 | |||
277 | return SUCCESS; | ||
278 | } | ||
279 | |||
280 | int rtp_send_msg ( rtp_session_t* _session, rtp_msg_t* _msg, void* _core_handler ) | ||
281 | { | ||
282 | if ( !_msg || _msg->_data == NULL || _msg->_length <= 0 ) { | ||
283 | t_perror ( RTP_ERROR_EMPTY_MESSAGE ); | ||
284 | return FAILURE; | ||
285 | } | ||
286 | |||
287 | int _last; | ||
288 | unsigned long long _total = 0; | ||
289 | |||
290 | size_t _length = _msg->_length; | ||
291 | uint8_t _send_data [ MAX_UDP_PACKET_SIZE ]; | ||
292 | |||
293 | uint16_t _prefix_length = _session->_prefix_length; | ||
294 | |||
295 | _send_data[0] = 70; | ||
296 | |||
297 | if ( _session->_prefix && _length + _prefix_length < MAX_UDP_PACKET_SIZE ) { | ||
298 | /*t_memcpy(_send_data, _session->_prefix, _prefix_length);*/ | ||
299 | t_memcpy ( _send_data + 1, _msg->_data, _length ); | ||
300 | } else { | ||
301 | t_memcpy ( _send_data + 1, _msg->_data, _length ); | ||
302 | } | ||
303 | |||
304 | /* Set sequ number */ | ||
305 | if ( _session->_sequence_number >= _MAX_SEQU_NUM ) { | ||
306 | _session->_sequence_number = 0; | ||
307 | } else { | ||
308 | _session->_sequence_number++; | ||
309 | } | ||
310 | |||
311 | /* Start sending loop */ | ||
312 | rtp_dest_list_t* _it; | ||
313 | for ( _it = _session->_dest_list; _it != NULL; _it = _it->next ) { | ||
314 | |||
315 | _last = m_sendpacket ( _core_handler, &_it->_dest, _send_data, _length + 1); | ||
316 | |||
317 | if ( _last < 0 ) { | ||
318 | t_perror ( RTP_ERROR_STD_SEND_FAILURE ); | ||
319 | printf("Stderror: %s", strerror(errno)); | ||
320 | } else { | ||
321 | _session->_packets_sent ++; | ||
322 | _total += _last; | ||
323 | } | ||
324 | |||
325 | } | ||
326 | |||
327 | rtp_free_msg ( _session, _msg ); | ||
328 | _session->_bytes_sent += _total; | ||
329 | return SUCCESS; | ||
330 | } | ||
331 | |||
332 | rtp_msg_t* rtp_recv_msg ( rtp_session_t* _session ) | ||
333 | { | ||
334 | if ( !_session ) | ||
335 | return NULL; | ||
336 | |||
337 | rtp_msg_t* _retu = _session->_oldest_msg; | ||
338 | |||
339 | pthread_mutex_lock(&_session->_mutex); | ||
340 | |||
341 | if ( _retu ) | ||
342 | _session->_oldest_msg = _retu->_next; | ||
343 | |||
344 | if ( !_session->_oldest_msg ) | ||
345 | _session->_last_msg = NULL; | ||
346 | |||
347 | pthread_mutex_unlock(&_session->_mutex); | ||
348 | |||
349 | return _retu; | ||
350 | } | ||
351 | |||
352 | void rtp_store_msg ( rtp_session_t* _session, rtp_msg_t* _msg ) | ||
353 | { | ||
354 | if ( rtp_check_late_message(_session, _msg) < 0 ) { | ||
355 | rtp_register_msg(_session, _msg); | ||
356 | } | ||
357 | |||
358 | pthread_mutex_lock(&_session->_mutex); | ||
359 | |||
360 | if ( _session->_last_msg ) { | ||
361 | _session->_last_msg->_next = _msg; | ||
362 | _session->_last_msg = _msg; | ||
363 | } else { | ||
364 | _session->_last_msg = _session->_oldest_msg = _msg; | ||
365 | } | ||
366 | |||
367 | pthread_mutex_unlock(&_session->_mutex); | ||
368 | return; | ||
369 | } | ||
370 | |||
371 | int rtp_release_session_recv ( rtp_session_t* _session ) | ||
372 | { | ||
373 | if ( !_session ){ | ||
374 | return FAILURE; | ||
375 | } | ||
376 | |||
377 | rtp_msg_t* _tmp,* _it; | ||
378 | |||
379 | pthread_mutex_lock(&_session->_mutex); | ||
380 | |||
381 | for ( _it = _session->_oldest_msg; _it; _it = _tmp ){ | ||
382 | _tmp = _it->_next; | ||
383 | rtp_free_msg(_session, _it); | ||
384 | } | ||
385 | |||
386 | _session->_last_msg = _session->_oldest_msg = NULL; | ||
387 | |||
388 | pthread_mutex_unlock(&_session->_mutex); | ||
389 | |||
390 | return SUCCESS; | ||
391 | } | ||
392 | |||
393 | rtp_msg_t* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length ) | ||
394 | { | ||
395 | if ( !_session ) | ||
396 | return NULL; | ||
397 | |||
398 | uint8_t* _from_pos; | ||
399 | rtp_msg_t* _retu = calloc(sizeof(rtp_msg_t), 1); | ||
400 | assert(_retu); | ||
401 | |||
402 | /* Sets header values and copies the extension header in _retu */ | ||
403 | _retu->_header = rtp_build_header ( _session ); /* It allocates memory and all */ | ||
404 | _retu->_ext_header = _session->_ext_header; | ||
405 | |||
406 | uint32_t _total_lenght = _length + _retu->_header->_length; | ||
407 | |||
408 | if ( _retu->_ext_header ) { | ||
409 | |||
410 | _total_lenght += ( _MIN_EXT_HEADER_LENGTH + _retu->_ext_header->_ext_len * size_32 ); | ||
411 | /* Allocate Memory for _retu->_data */ | ||
412 | _retu->_data = calloc ( sizeof _retu->_data, _total_lenght ); | ||
413 | assert(_retu->_data); | ||
414 | |||
415 | _from_pos = rtp_add_header ( _retu->_header, _retu->_data ); | ||
416 | _from_pos = rtp_add_extention_header ( _retu->_ext_header, _from_pos + 1 ); | ||
417 | } else { | ||
418 | /* Allocate Memory for _retu->_data */ | ||
419 | _retu->_data = calloc ( sizeof _retu->_data, _total_lenght ); | ||
420 | assert(_retu->_data); | ||
421 | |||
422 | _from_pos = rtp_add_header ( _retu->_header, _retu->_data ); | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * Parses the extension header into the message | ||
427 | * Of course if any | ||
428 | */ | ||
429 | |||
430 | /* Appends _data on to _retu->_data */ | ||
431 | t_memcpy ( _from_pos + 1, _data, _length ); | ||
432 | |||
433 | _retu->_length = _total_lenght; | ||
434 | |||
435 | _retu->_next = NULL; | ||
436 | |||
437 | return _retu; | ||
438 | } | ||
439 | |||
440 | rtp_msg_t* rtp_msg_parse ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length ) | ||
441 | { | ||
442 | rtp_msg_t* _retu = calloc(sizeof(rtp_msg_t), 1); | ||
443 | assert(_retu); | ||
444 | |||
445 | _retu->_header = rtp_extract_header ( _data, _length ); /* It allocates memory and all */ | ||
446 | if ( !_retu->_header ){ | ||
447 | free(_retu); | ||
448 | return NULL; | ||
449 | } | ||
450 | |||
451 | _retu->_length = _length - _retu->_header->_length; | ||
452 | |||
453 | uint16_t _from_pos = _retu->_header->_length; | ||
454 | |||
455 | |||
456 | if ( rtp_header_get_flag_extension ( _retu->_header ) ) { | ||
457 | _retu->_ext_header = rtp_extract_ext_header ( _data + _from_pos, _length ); | ||
458 | if ( _retu->_ext_header ){ | ||
459 | _retu->_length -= ( _MIN_EXT_HEADER_LENGTH + _retu->_ext_header->_ext_len * size_32 ); | ||
460 | _from_pos += ( _MIN_EXT_HEADER_LENGTH + _retu->_ext_header->_ext_len * size_32 ); | ||
461 | } else { | ||
462 | free (_retu->_ext_header); | ||
463 | free (_retu->_header); | ||
464 | free (_retu); | ||
465 | return NULL; | ||
466 | } | ||
467 | } else { | ||
468 | _retu->_ext_header = NULL; | ||
469 | } | ||
470 | |||
471 | /* Get the payload */ | ||
472 | _retu->_data = calloc ( sizeof ( uint8_t ), _retu->_length ); | ||
473 | assert(_retu->_data); | ||
474 | |||
475 | t_memcpy ( _retu->_data, _data + _from_pos, _length - _from_pos ); | ||
476 | |||
477 | _retu->_next = NULL; | ||
478 | |||
479 | |||
480 | if ( _session && !_session->_multi_session && rtp_check_late_message(_session, _retu) < 0 ){ | ||
481 | rtp_register_msg(_session, _retu); | ||
482 | } | ||
483 | |||
484 | return _retu; | ||
485 | } | ||
486 | |||
487 | int rtp_check_late_message (rtp_session_t* _session, rtp_msg_t* _msg) | ||
488 | { | ||
489 | /* | ||
490 | * Check Sequence number. If this new msg has lesser number then the _session->_last_sequence_number | ||
491 | * it shows that the message came in late | ||
492 | */ | ||
493 | if ( _msg->_header->_sequence_number < _session->_last_sequence_number && | ||
494 | _msg->_header->_timestamp < _session->_current_timestamp | ||
495 | ) { | ||
496 | return SUCCESS; /* Drop the packet. You can check if the packet dropped by checking _packet_loss increment. */ | ||
497 | } | ||
498 | return FAILURE; | ||
499 | } | ||
500 | |||
501 | void rtp_register_msg ( rtp_session_t* _session, rtp_msg_t* _msg ) | ||
502 | { | ||
503 | _session->_last_sequence_number = _msg->_header->_sequence_number; | ||
504 | _session->_current_timestamp = _msg->_header->_timestamp; | ||
505 | } | ||
506 | |||
507 | |||
508 | int rtp_add_resolution_marking ( rtp_session_t* _session, uint16_t _width, uint16_t _height ) | ||
509 | { | ||
510 | if ( !_session ) | ||
511 | return FAILURE; | ||
512 | |||
513 | rtp_ext_header_t* _ext_header = _session->_ext_header; | ||
514 | _session->_exthdr_resolution = 0; | ||
515 | |||
516 | if ( ! ( _ext_header ) ) { | ||
517 | _session->_ext_header = calloc (sizeof(rtp_ext_header_t), 1); | ||
518 | assert(_session->_ext_header); | ||
519 | |||
520 | _session->_extension = 1; | ||
521 | _session->_ext_header->_ext_len = 1; | ||
522 | _ext_header = _session->_ext_header; | ||
523 | _session->_ext_header->_hd_ext = calloc(sizeof(uint32_t), 1); | ||
524 | assert(_session->_ext_header->_hd_ext); | ||
525 | |||
526 | } else { /* If there is need for more headers this will be needed to change */ | ||
527 | if ( !(_ext_header->_ext_type & RTP_EXT_TYPE_RESOLUTION) ){ | ||
528 | uint32_t _exthdr_framerate = _ext_header->_hd_ext[_session->_exthdr_framerate]; | ||
529 | /* it's position is at 2nd place by default */ | ||
530 | _session->_exthdr_framerate ++; | ||
531 | |||
532 | /* Update length */ | ||
533 | _ext_header->_ext_len++; | ||
534 | |||
535 | /* Allocate the value */ | ||
536 | _ext_header->_hd_ext = realloc(_ext_header->_hd_ext, sizeof(rtp_ext_header_t) * _ext_header->_ext_len); | ||
537 | assert(_ext_header->_hd_ext); | ||
538 | |||
539 | /* Reset other values */ | ||
540 | _ext_header->_hd_ext[_session->_exthdr_framerate] = _exthdr_framerate; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | /* Add flag */ | ||
545 | _ext_header->_ext_type |= RTP_EXT_TYPE_RESOLUTION; | ||
546 | |||
547 | _ext_header->_hd_ext[_session->_exthdr_resolution] = _width << 16 | ( uint32_t ) _height; | ||
548 | |||
549 | return SUCCESS; | ||
550 | } | ||
551 | |||
552 | int rtp_remove_resolution_marking ( rtp_session_t* _session ) | ||
553 | { | ||
554 | if ( _session->_extension == 0 || ! ( _session->_ext_header ) ) { | ||
555 | t_perror ( RTP_ERROR_INVALID_EXTERNAL_HEADER ); | ||
556 | return FAILURE; | ||
557 | } | ||
558 | |||
559 | if ( !( _session->_ext_header->_ext_type & RTP_EXT_TYPE_RESOLUTION ) ) { | ||
560 | t_perror ( RTP_ERROR_INVALID_EXTERNAL_HEADER ); | ||
561 | return FAILURE; | ||
562 | } | ||
563 | |||
564 | _session->_ext_header->_ext_type &= ~RTP_EXT_TYPE_RESOLUTION; /* Remove the flag */ | ||
565 | _session->_exthdr_resolution = -1; /* Remove identifier */ | ||
566 | |||
567 | /* Check if extension is empty */ | ||
568 | if ( _session->_ext_header->_ext_type == 0 ){ | ||
569 | |||
570 | free ( _session->_ext_header->_hd_ext ); | ||
571 | free ( _session->_ext_header ); | ||
572 | |||
573 | _session->_ext_header = NULL; /* It's very important */ | ||
574 | _session->_extension = 0; | ||
575 | |||
576 | } else { | ||
577 | _session->_ext_header->_ext_len --; | ||
578 | |||
579 | /* this will also be needed to change if there are more than 2 headers */ | ||
580 | if ( _session->_ext_header->_ext_type & RTP_EXT_TYPE_FRAMERATE ){ | ||
581 | memcpy(_session->_ext_header->_hd_ext + 1, _session->_ext_header->_hd_ext, _session->_ext_header->_ext_len); | ||
582 | _session->_exthdr_framerate = 0; | ||
583 | _session->_ext_header->_hd_ext = realloc( _session->_ext_header->_hd_ext, sizeof( rtp_ext_header_t ) * _session->_ext_header->_ext_len ); | ||
584 | assert(_session->_ext_header->_hd_ext); | ||
585 | } | ||
586 | } | ||
587 | |||
588 | return SUCCESS; | ||
589 | } | ||
590 | |||
591 | int rtp_add_framerate_marking ( rtp_session_t* _session, uint32_t _value ) | ||
592 | { | ||
593 | if ( !_session ) | ||
594 | return FAILURE; | ||
595 | |||
596 | rtp_ext_header_t* _ext_header = _session->_ext_header; | ||
597 | _session->_exthdr_framerate = 0; | ||
598 | |||
599 | if ( ! ( _ext_header ) ) { | ||
600 | _session->_ext_header = calloc (sizeof(rtp_ext_header_t), 1); | ||
601 | assert(_session->_ext_header); | ||
602 | |||
603 | _session->_extension = 1; | ||
604 | _session->_ext_header->_ext_len = 1; | ||
605 | _ext_header = _session->_ext_header; | ||
606 | _session->_ext_header->_hd_ext = calloc(sizeof(uint32_t), 1); | ||
607 | assert(_session->_ext_header->_hd_ext); | ||
608 | } else { /* If there is need for more headers this will be needed to change */ | ||
609 | if ( !(_ext_header->_ext_type & RTP_EXT_TYPE_FRAMERATE) ){ | ||
610 | /* it's position is at 2nd place by default */ | ||
611 | _session->_exthdr_framerate ++; | ||
612 | |||
613 | /* Update length */ | ||
614 | _ext_header->_ext_len++; | ||
615 | |||
616 | /* Allocate the value */ | ||
617 | _ext_header->_hd_ext = realloc(_ext_header->_hd_ext, sizeof(rtp_ext_header_t) * _ext_header->_ext_len); | ||
618 | assert(_ext_header->_hd_ext); | ||
619 | |||
620 | } | ||
621 | } | ||
622 | |||
623 | /* Add flag */ | ||
624 | _ext_header->_ext_type |= RTP_EXT_TYPE_FRAMERATE; | ||
625 | |||
626 | _ext_header->_hd_ext[_session->_exthdr_framerate] = _value; | ||
627 | |||
628 | return SUCCESS; | ||
629 | } | ||
630 | |||
631 | |||
632 | int rtp_remove_framerate_marking ( rtp_session_t* _session ) | ||
633 | { | ||
634 | if ( _session->_extension == 0 || ! ( _session->_ext_header ) ) { | ||
635 | t_perror ( RTP_ERROR_INVALID_EXTERNAL_HEADER ); | ||
636 | return FAILURE; | ||
637 | } | ||
638 | |||
639 | if ( !( _session->_ext_header->_ext_type & RTP_EXT_TYPE_FRAMERATE ) ) { | ||
640 | t_perror ( RTP_ERROR_INVALID_EXTERNAL_HEADER ); | ||
641 | return FAILURE; | ||
642 | } | ||
643 | |||
644 | _session->_ext_header->_ext_type &= ~RTP_EXT_TYPE_FRAMERATE; /* Remove the flag */ | ||
645 | _session->_exthdr_framerate = -1; /* Remove identifier */ | ||
646 | _session->_ext_header->_ext_len --; | ||
647 | |||
648 | /* Check if extension is empty */ | ||
649 | if ( _session->_ext_header->_ext_type == 0 ){ | ||
650 | |||
651 | free ( _session->_ext_header->_hd_ext ); | ||
652 | free ( _session->_ext_header ); | ||
653 | |||
654 | _session->_ext_header = NULL; /* It's very important */ | ||
655 | _session->_extension = 0; | ||
656 | |||
657 | } else if ( !_session->_ext_header->_ext_len ) { | ||
658 | |||
659 | /* this will also be needed to change if there are more than 2 headers */ | ||
660 | _session->_ext_header->_hd_ext = realloc( _session->_ext_header->_hd_ext, sizeof( rtp_ext_header_t ) * _session->_ext_header->_ext_len ); | ||
661 | assert(_session->_ext_header->_hd_ext); | ||
662 | |||
663 | } | ||
664 | |||
665 | return SUCCESS; | ||
666 | } | ||
667 | |||
668 | uint32_t rtp_get_framerate_marking ( rtp_ext_header_t* _header ) | ||
669 | { | ||
670 | if ( _header->_ext_len == 1 ){ | ||
671 | return _header->_hd_ext[0]; | ||
672 | } else { | ||
673 | return _header->_hd_ext[1]; | ||
674 | } | ||
675 | } | ||
676 | |||
677 | int rtp_set_prefix ( rtp_session_t* _session, uint8_t* _prefix, uint16_t _prefix_length ) | ||
678 | { | ||
679 | if ( !_session ) | ||
680 | return FAILURE; | ||
681 | |||
682 | if ( _session->_prefix ) { | ||
683 | free ( _session->_prefix ); | ||
684 | } | ||
685 | |||
686 | _session->_prefix = calloc ( ( sizeof * _session->_prefix ), _prefix_length ); | ||
687 | assert(_session->_prefix); | ||
688 | |||
689 | t_memcpy ( _session->_prefix, _prefix, _prefix_length ); | ||
690 | _session->_prefix_length = _prefix_length; | ||
691 | |||
692 | return SUCCESS; | ||
693 | } | ||