diff options
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/msi.c | 194 | ||||
-rw-r--r-- | toxav/msi.h | 28 | ||||
-rw-r--r-- | toxav/toxav.c | 133 | ||||
-rw-r--r-- | toxav/toxav.h | 43 |
4 files changed, 268 insertions, 130 deletions
diff --git a/toxav/msi.c b/toxav/msi.c index 73429a81..0bff20f8 100644 --- a/toxav/msi.c +++ b/toxav/msi.c | |||
@@ -48,13 +48,14 @@ | |||
48 | * |id [1 byte]| |size [1 byte]| |data [$size bytes]| |...{repeat}| |0 {end byte}| | 48 | * |id [1 byte]| |size [1 byte]| |data [$size bytes]| |...{repeat}| |0 {end byte}| |
49 | */ | 49 | */ |
50 | 50 | ||
51 | typedef uint8_t MSIRawCSettingsType[23]; | ||
51 | 52 | ||
52 | typedef enum { | 53 | typedef enum { |
53 | IDRequest = 1, | 54 | IDRequest = 1, |
54 | IDResponse, | 55 | IDResponse, |
55 | IDReason, | 56 | IDReason, |
56 | IDCallType, | ||
57 | IDCallId, | 57 | IDCallId, |
58 | IDCSettings, | ||
58 | 59 | ||
59 | } MSIHeaderID; | 60 | } MSIHeaderID; |
60 | 61 | ||
@@ -91,9 +92,9 @@ _Bool exists; \ | |||
91 | 92 | ||
92 | GENERIC_HEADER ( Request, MSIRequest ) | 93 | GENERIC_HEADER ( Request, MSIRequest ) |
93 | GENERIC_HEADER ( Response, MSIResponse ) | 94 | GENERIC_HEADER ( Response, MSIResponse ) |
94 | GENERIC_HEADER ( CallType, MSICallType ) | ||
95 | GENERIC_HEADER ( CallId, MSICallIDType ) | 95 | GENERIC_HEADER ( CallId, MSICallIDType ) |
96 | GENERIC_HEADER ( Reason, MSIReasonStrType ) | 96 | GENERIC_HEADER ( Reason, MSIReasonStrType ) |
97 | GENERIC_HEADER ( CSettings, MSIRawCSettingsType ) | ||
97 | 98 | ||
98 | 99 | ||
99 | /** | 100 | /** |
@@ -105,10 +106,10 @@ typedef struct _MSIMessage { | |||
105 | 106 | ||
106 | MSIHeaderRequest request; | 107 | MSIHeaderRequest request; |
107 | MSIHeaderResponse response; | 108 | MSIHeaderResponse response; |
108 | MSIHeaderCallType calltype; | ||
109 | MSIHeaderReason reason; | 109 | MSIHeaderReason reason; |
110 | MSIHeaderCallId callid; | 110 | MSIHeaderCallId callid; |
111 | 111 | MSIHeaderCSettings csettings; | |
112 | |||
112 | int friend_id; | 113 | int friend_id; |
113 | 114 | ||
114 | } MSIMessage; | 115 | } MSIMessage; |
@@ -173,15 +174,6 @@ static int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t lengt | |||
173 | msg->response.exists = 1; | 174 | msg->response.exists = 1; |
174 | break; | 175 | break; |
175 | 176 | ||
176 | case IDCallType: | ||
177 | FAIL_CONSTRAINT(size_constraint, 3); | ||
178 | FAIL_SIZE(it[1], 1); | ||
179 | FAIL_LIMITS(it[2], type_audio, type_video); | ||
180 | msg->calltype.value = it[2]; | ||
181 | it += 3; | ||
182 | msg->calltype.exists = 1; | ||
183 | break; | ||
184 | |||
185 | case IDCallId: | 177 | case IDCallId: |
186 | FAIL_CONSTRAINT(size_constraint, sizeof(MSICallIDType) + 2); | 178 | FAIL_CONSTRAINT(size_constraint, sizeof(MSICallIDType) + 2); |
187 | FAIL_SIZE(it[1], sizeof(MSICallIDType)); | 179 | FAIL_SIZE(it[1], sizeof(MSICallIDType)); |
@@ -197,7 +189,14 @@ static int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t lengt | |||
197 | it += sizeof(MSIReasonStrType) + 2; | 189 | it += sizeof(MSIReasonStrType) + 2; |
198 | msg->reason.exists = 1; | 190 | msg->reason.exists = 1; |
199 | break; | 191 | break; |
200 | 192 | ||
193 | case IDCSettings: | ||
194 | FAIL_CONSTRAINT(size_constraint, sizeof(MSIRawCSettingsType) + 2); | ||
195 | FAIL_SIZE(it[1], sizeof(MSIRawCSettingsType)); | ||
196 | memcpy(msg->csettings.value, it + 2, sizeof(MSIRawCSettingsType)); | ||
197 | it += sizeof(MSIRawCSettingsType) + 2; | ||
198 | msg->csettings.exists = 1; | ||
199 | break; | ||
201 | default: | 200 | default: |
202 | LOGGER_ERROR("Invalid id byte"); | 201 | LOGGER_ERROR("Invalid id byte"); |
203 | return -1; | 202 | return -1; |
@@ -336,18 +335,17 @@ uint16_t parse_send ( MSIMessage *msg, uint8_t *dest ) | |||
336 | it = format_output(it, IDResponse, &cast, 1, &size); | 335 | it = format_output(it, IDResponse, &cast, 1, &size); |
337 | } | 336 | } |
338 | 337 | ||
339 | if (msg->calltype.exists) { | ||
340 | uint8_t cast = msg->calltype.value; | ||
341 | it = format_output(it, IDCallType, &cast, 1, &size); | ||
342 | } | ||
343 | |||
344 | if (msg->callid.exists) { | 338 | if (msg->callid.exists) { |
345 | it = format_output(it, IDCallId, &msg->callid.value, sizeof(msg->callid.value), &size); | 339 | it = format_output(it, IDCallId, &msg->callid.value, sizeof(msg->callid.value), &size); |
346 | } | 340 | } |
347 | 341 | ||
348 | if (msg->reason.exists) { | 342 | if (msg->reason.exists) { |
349 | it = format_output(it, IDReason, &msg->reason.value, sizeof(msg->reason.value), &size); | 343 | it = format_output(it, IDReason, &msg->reason.value, sizeof(msg->reason.value), &size); |
350 | } | 344 | } |
345 | |||
346 | if (msg->csettings.exists) { | ||
347 | it = format_output(it, IDCSettings, &msg->csettings.value, sizeof(msg->csettings.value), &size); | ||
348 | } | ||
351 | 349 | ||
352 | *it = 0; | 350 | *it = 0; |
353 | size ++; | 351 | size ++; |
@@ -355,15 +353,6 @@ uint16_t parse_send ( MSIMessage *msg, uint8_t *dest ) | |||
355 | return size; | 353 | return size; |
356 | } | 354 | } |
357 | 355 | ||
358 | |||
359 | void msi_msg_set_calltype ( MSIMessage *msg, const MSICallType value ) | ||
360 | { | ||
361 | if ( !msg ) return; | ||
362 | |||
363 | msg->calltype.exists = 1; | ||
364 | msg->calltype.value = value; | ||
365 | } | ||
366 | |||
367 | void msi_msg_set_reason ( MSIMessage *msg, const MSIReasonStrType value ) | 356 | void msi_msg_set_reason ( MSIMessage *msg, const MSIReasonStrType value ) |
368 | { | 357 | { |
369 | if ( !msg ) return; | 358 | if ( !msg ) return; |
@@ -380,6 +369,72 @@ void msi_msg_set_callid ( MSIMessage *msg, const MSICallIDType value ) | |||
380 | memcpy(msg->callid.value, value, sizeof(MSICallIDType)); | 369 | memcpy(msg->callid.value, value, sizeof(MSICallIDType)); |
381 | } | 370 | } |
382 | 371 | ||
372 | void msi_msg_set_csettings ( MSIMessage *msg, const MSICSettings* value ) | ||
373 | { | ||
374 | if ( !msg ) return; | ||
375 | |||
376 | msg->csettings.exists = 1; | ||
377 | |||
378 | msg->csettings.value[0] = value->call_type; | ||
379 | uint8_t* iter = msg->csettings.value + 1; | ||
380 | |||
381 | /* Video bitrate */ | ||
382 | uint32_t lval = htonl(value->video_bitrate); | ||
383 | memcpy(iter, &lval, 4); iter += 4; | ||
384 | |||
385 | /* Video max width */ | ||
386 | uint16_t sval= htons(value->max_video_width); | ||
387 | memcpy(iter, &sval, 2); iter += 2; | ||
388 | |||
389 | /* Video max height */ | ||
390 | sval= htons(value->max_video_height); | ||
391 | memcpy(iter, &sval, 2); iter += 2; | ||
392 | |||
393 | /* Audio bitrate */ | ||
394 | lval = htonl(value->audio_bitrate); | ||
395 | memcpy(iter, &lval, 4); iter += 4; | ||
396 | |||
397 | /* Audio frame duration */ | ||
398 | sval= htons(value->audio_frame_duration); | ||
399 | memcpy(iter, &sval, 2); iter += 2; | ||
400 | |||
401 | /* Audio sample rate */ | ||
402 | lval = htonl(value->audio_sample_rate); | ||
403 | memcpy(iter, &lval, 4); iter += 4; | ||
404 | |||
405 | /* Audio channels */ | ||
406 | lval = htonl(value->audio_channels); | ||
407 | memcpy(iter, &lval, 4); | ||
408 | } | ||
409 | |||
410 | void msi_msg_get_csettings ( MSIMessage *msg, MSICSettings* dest ) | ||
411 | { | ||
412 | if ( !msg || !dest || !msg->csettings.exists ) return; | ||
413 | |||
414 | dest->call_type = msg->csettings.value[0]; | ||
415 | uint8_t* iter = msg->csettings.value + 1; | ||
416 | |||
417 | memcpy(&dest->video_bitrate, iter, 4); iter += 4; | ||
418 | dest->video_bitrate = ntohl(dest->video_bitrate); | ||
419 | |||
420 | memcpy(&dest->max_video_width, iter, 2); iter += 2; | ||
421 | dest->max_video_width = ntohs(dest->max_video_width); | ||
422 | |||
423 | memcpy(&dest->max_video_height, iter, 2); iter += 2; | ||
424 | dest->max_video_height = ntohs(dest->max_video_height); | ||
425 | |||
426 | memcpy(&dest->audio_bitrate, iter, 4); iter += 4; | ||
427 | dest->audio_bitrate = ntohl(dest->audio_bitrate); | ||
428 | |||
429 | memcpy(&dest->audio_frame_duration, iter, 2); iter += 2; | ||
430 | dest->audio_frame_duration = ntohs(dest->audio_frame_duration); | ||
431 | |||
432 | memcpy(&dest->audio_sample_rate, iter, 4); iter += 4; | ||
433 | dest->audio_sample_rate = ntohl(dest->audio_sample_rate); | ||
434 | |||
435 | memcpy(&dest->audio_channels, iter, 4); | ||
436 | dest->audio_channels = ntohl(dest->audio_channels); | ||
437 | } | ||
383 | 438 | ||
384 | typedef struct _Timer { | 439 | typedef struct _Timer { |
385 | void *(*func)(void *); | 440 | void *(*func)(void *); |
@@ -753,14 +808,33 @@ static int call_id_bigger( const uint8_t *first, const uint8_t *second) | |||
753 | * @param peer_id The peer. | 808 | * @param peer_id The peer. |
754 | * @return -1, 0 | 809 | * @return -1, 0 |
755 | */ | 810 | */ |
756 | static int flush_peer_type ( MSICall *call, MSIMessage *msg, int peer_id ) | 811 | static int flush_peer_csettings ( MSICall *call, MSIMessage *msg, int peer_id ) |
757 | { | 812 | { |
758 | if ( msg->calltype.exists ) { | 813 | if ( msg->csettings.exists ) { |
759 | call->type_peer[peer_id] = msg->calltype.value; | 814 | msi_msg_get_csettings(msg, &call->csettings_peer[peer_id]); |
815 | |||
816 | LOGGER_DEBUG("Peer: %d \n" | ||
817 | "Type: %u \n" | ||
818 | "Video bitrate: %u \n" | ||
819 | "Video height: %u \n" | ||
820 | "Video width: %u \n" | ||
821 | "Audio bitrate: %u \n" | ||
822 | "Audio framedur: %u \n" | ||
823 | "Audio sample rate: %u \n" | ||
824 | "Audio channels: %u \n", peer_id, | ||
825 | call->csettings_peer[peer_id].call_type, | ||
826 | call->csettings_peer[peer_id].video_bitrate, | ||
827 | call->csettings_peer[peer_id].max_video_height, | ||
828 | call->csettings_peer[peer_id].max_video_width, | ||
829 | call->csettings_peer[peer_id].audio_bitrate, | ||
830 | call->csettings_peer[peer_id].audio_frame_duration, | ||
831 | call->csettings_peer[peer_id].audio_sample_rate, | ||
832 | call->csettings_peer[peer_id].audio_channels ); | ||
833 | |||
760 | return 0; | 834 | return 0; |
761 | } | 835 | } |
762 | 836 | ||
763 | LOGGER_WARNING("No call type header!"); | 837 | LOGGER_WARNING("No csettings header!"); |
764 | return -1; | 838 | return -1; |
765 | } | 839 | } |
766 | 840 | ||
@@ -904,7 +978,7 @@ static MSICall *init_call ( MSISession *session, int peers, int ringing_timeout | |||
904 | 978 | ||
905 | call->call_idx = call_idx; | 979 | call->call_idx = call_idx; |
906 | 980 | ||
907 | if ( !(call->type_peer = calloc ( sizeof ( MSICallType ), peers )) ) { | 981 | if ( !(call->csettings_peer = calloc ( sizeof ( MSICSettings ), peers )) ) { |
908 | LOGGER_WARNING("Allocation failed! Program might misbehave!"); | 982 | LOGGER_WARNING("Allocation failed! Program might misbehave!"); |
909 | free(call); | 983 | free(call); |
910 | return NULL; | 984 | return NULL; |
@@ -912,8 +986,6 @@ static MSICall *init_call ( MSISession *session, int peers, int ringing_timeout | |||
912 | 986 | ||
913 | call->session = session; | 987 | call->session = session; |
914 | 988 | ||
915 | /*_call->_participant_count = _peers;*/ | ||
916 | |||
917 | call->request_timer_id = 0; | 989 | call->request_timer_id = 0; |
918 | call->ringing_timer_id = 0; | 990 | call->ringing_timer_id = 0; |
919 | 991 | ||
@@ -954,7 +1026,7 @@ static int terminate_call ( MSISession *session, MSICall *call ) | |||
954 | 1026 | ||
955 | session->calls[call->call_idx] = NULL; | 1027 | session->calls[call->call_idx] = NULL; |
956 | 1028 | ||
957 | free ( call->type_peer ); | 1029 | free ( call->csettings_peer ); |
958 | free ( call->peers); | 1030 | free ( call->peers); |
959 | 1031 | ||
960 | /* Release handle */ | 1032 | /* Release handle */ |
@@ -1012,13 +1084,13 @@ static int handle_recv_invite ( MSISession *session, MSICall *call, MSIMessage * | |||
1012 | 1084 | ||
1013 | pthread_mutex_lock(&session->mutex); | 1085 | pthread_mutex_lock(&session->mutex); |
1014 | 1086 | ||
1015 | if (!msg->calltype.exists) {/**/ | 1087 | if (!msg->csettings.exists) {/**/ |
1016 | LOGGER_WARNING("Peer sent invalid call type!"); | 1088 | LOGGER_WARNING("Peer sent invalid codec settings!"); |
1017 | send_error ( session, call, error_no_callid, msg->friend_id ); | 1089 | send_error ( session, call, error_no_callid, msg->friend_id ); |
1018 | pthread_mutex_unlock(&session->mutex); | 1090 | pthread_mutex_unlock(&session->mutex); |
1019 | return 0; | 1091 | return 0; |
1020 | } | 1092 | } |
1021 | 1093 | ||
1022 | if ( call ) { | 1094 | if ( call ) { |
1023 | if ( call->peers[0] == msg->friend_id ) { | 1095 | if ( call->peers[0] == msg->friend_id ) { |
1024 | if (call->state == call_inviting) { | 1096 | if (call->state == call_inviting) { |
@@ -1049,14 +1121,14 @@ static int handle_recv_invite ( MSISession *session, MSICall *call, MSIMessage * | |||
1049 | } | 1121 | } |
1050 | } else if (call->state == call_active) { | 1122 | } else if (call->state == call_active) { |
1051 | /* Request for media change; call callback and send starting response */ | 1123 | /* Request for media change; call callback and send starting response */ |
1052 | if (flush_peer_type(call, msg, 0) != 0) { /**/ | 1124 | if (flush_peer_csettings(call, msg, 0) != 0) { /**/ |
1053 | LOGGER_WARNING("Peer sent invalid call type!"); | 1125 | LOGGER_WARNING("Peer sent invalid csetting!"); |
1054 | send_error ( session, call, error_no_callid, msg->friend_id ); | 1126 | send_error ( session, call, error_no_callid, msg->friend_id ); |
1055 | pthread_mutex_unlock(&session->mutex); | 1127 | pthread_mutex_unlock(&session->mutex); |
1056 | return 0; | 1128 | return 0; |
1057 | } | 1129 | } |
1058 | 1130 | ||
1059 | LOGGER_DEBUG("Set new call type: %s", call->type_peer[0] == type_audio ? "audio" : "video"); | 1131 | LOGGER_DEBUG("Set new call type: %s", call->csettings_peer[0].call_type == type_audio ? "audio" : "video"); |
1060 | send_reponse(session, call, starting, msg->friend_id); | 1132 | send_reponse(session, call, starting, msg->friend_id); |
1061 | pthread_mutex_unlock(&session->mutex); | 1133 | pthread_mutex_unlock(&session->mutex); |
1062 | invoke_callback(session, call->call_idx, MSI_OnMediaChange); | 1134 | invoke_callback(session, call->call_idx, MSI_OnMediaChange); |
@@ -1090,7 +1162,7 @@ static int handle_recv_invite ( MSISession *session, MSICall *call, MSIMessage * | |||
1090 | 1162 | ||
1091 | add_peer( call, msg->friend_id); | 1163 | add_peer( call, msg->friend_id); |
1092 | 1164 | ||
1093 | flush_peer_type ( call, msg, 0 ); | 1165 | flush_peer_csettings ( call, msg, 0 ); |
1094 | 1166 | ||
1095 | send_reponse(session, call, ringing, msg->friend_id); | 1167 | send_reponse(session, call, ringing, msg->friend_id); |
1096 | 1168 | ||
@@ -1234,7 +1306,7 @@ static int handle_recv_starting ( MSISession *session, MSICall *call, MSIMessage | |||
1234 | free ( msg_start ); | 1306 | free ( msg_start ); |
1235 | 1307 | ||
1236 | 1308 | ||
1237 | flush_peer_type ( call, msg, 0 ); | 1309 | flush_peer_csettings ( call, msg, 0 ); |
1238 | 1310 | ||
1239 | /* This is here in case of glare */ | 1311 | /* This is here in case of glare */ |
1240 | timer_release ( session->timer_handler, call->ringing_timer_id, 1 ); | 1312 | timer_release ( session->timer_handler, call->ringing_timer_id, 1 ); |
@@ -1536,7 +1608,7 @@ int msi_terminate_session ( MSISession *session ) | |||
1536 | * @param friend_id The friend. | 1608 | * @param friend_id The friend. |
1537 | * @return int | 1609 | * @return int |
1538 | */ | 1610 | */ |
1539 | int msi_invite ( MSISession *session, int32_t *call_index, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ) | 1611 | int msi_invite ( MSISession *session, int32_t *call_index, MSICSettings csettings, uint32_t rngsec, uint32_t friend_id ) |
1540 | { | 1612 | { |
1541 | pthread_mutex_lock(&session->mutex); | 1613 | pthread_mutex_lock(&session->mutex); |
1542 | 1614 | ||
@@ -1567,11 +1639,11 @@ int msi_invite ( MSISession *session, int32_t *call_index, MSICallType call_type | |||
1567 | 1639 | ||
1568 | add_peer ( call, friend_id ); | 1640 | add_peer ( call, friend_id ); |
1569 | 1641 | ||
1570 | call->type_local = call_type; | 1642 | call->csettings_local = csettings; |
1571 | 1643 | ||
1572 | MSIMessage *msg_invite = msi_new_message ( TypeRequest, invite ); | 1644 | MSIMessage *msg_invite = msi_new_message ( TypeRequest, invite ); |
1573 | 1645 | ||
1574 | msi_msg_set_calltype(msg_invite, call_type); | 1646 | msi_msg_set_csettings(msg_invite, &csettings); |
1575 | send_message ( session, call, msg_invite, friend_id ); | 1647 | send_message ( session, call, msg_invite, friend_id ); |
1576 | free( msg_invite ); | 1648 | free( msg_invite ); |
1577 | 1649 | ||
@@ -1641,7 +1713,7 @@ int msi_hangup ( MSISession *session, int32_t call_index ) | |||
1641 | * @param call_type Answer with Audio or Video(both). | 1713 | * @param call_type Answer with Audio or Video(both). |
1642 | * @return int | 1714 | * @return int |
1643 | */ | 1715 | */ |
1644 | int msi_answer ( MSISession *session, int32_t call_index, MSICallType call_type ) | 1716 | int msi_answer ( MSISession *session, int32_t call_index, MSICSettings csettings ) |
1645 | { | 1717 | { |
1646 | pthread_mutex_lock(&session->mutex); | 1718 | pthread_mutex_lock(&session->mutex); |
1647 | LOGGER_DEBUG("Session: %p Answering call: %u", session, call_index); | 1719 | LOGGER_DEBUG("Session: %p Answering call: %u", session, call_index); |
@@ -1654,9 +1726,9 @@ int msi_answer ( MSISession *session, int32_t call_index, MSICallType call_type | |||
1654 | 1726 | ||
1655 | MSIMessage *msg_starting = msi_new_message ( TypeResponse, starting ); | 1727 | MSIMessage *msg_starting = msi_new_message ( TypeResponse, starting ); |
1656 | 1728 | ||
1657 | session->calls[call_index]->type_local = call_type; | 1729 | session->calls[call_index]->csettings_local = csettings; |
1658 | 1730 | ||
1659 | msi_msg_set_calltype(msg_starting, call_type); | 1731 | msi_msg_set_csettings(msg_starting, &csettings); |
1660 | 1732 | ||
1661 | send_message ( session, session->calls[call_index], msg_starting, session->calls[call_index]->peers[0] ); | 1733 | send_message ( session, session->calls[call_index], msg_starting, session->calls[call_index]->peers[0] ); |
1662 | free ( msg_starting ); | 1734 | free ( msg_starting ); |
@@ -1766,7 +1838,7 @@ int msi_reject ( MSISession *session, int32_t call_index, const char *reason ) | |||
1766 | * @param friend_id The friend. | 1838 | * @param friend_id The friend. |
1767 | * @return int | 1839 | * @return int |
1768 | */ | 1840 | */ |
1769 | int msi_change_type(MSISession *session, int32_t call_index, MSICallType call_type) | 1841 | int msi_change_csettings(MSISession* session, int32_t call_index, MSICSettings csettings) |
1770 | { | 1842 | { |
1771 | pthread_mutex_lock(&session->mutex); | 1843 | pthread_mutex_lock(&session->mutex); |
1772 | 1844 | ||
@@ -1786,17 +1858,27 @@ int msi_change_type(MSISession *session, int32_t call_index, MSICallType call_ty | |||
1786 | return -1; | 1858 | return -1; |
1787 | } | 1859 | } |
1788 | 1860 | ||
1789 | if ( call->type_local == call_type ) { | 1861 | MSICSettings *local = &call->csettings_local; |
1790 | LOGGER_ERROR("Call is already set to the requested type!"); | 1862 | if ( |
1863 | local->call_type == csettings.call_type && | ||
1864 | local->video_bitrate == csettings.video_bitrate && | ||
1865 | local->max_video_width == csettings.max_video_width && | ||
1866 | local->max_video_height == csettings.max_video_height && | ||
1867 | local->audio_bitrate == csettings.audio_bitrate && | ||
1868 | local->audio_frame_duration == csettings.audio_frame_duration && | ||
1869 | local->audio_sample_rate == csettings.audio_sample_rate && | ||
1870 | local->audio_channels == csettings.audio_channels ) | ||
1871 | { | ||
1872 | LOGGER_ERROR("Call is already set accordingly!"); | ||
1791 | pthread_mutex_unlock(&session->mutex); | 1873 | pthread_mutex_unlock(&session->mutex); |
1792 | return -1; | 1874 | return -1; |
1793 | } | 1875 | } |
1794 | 1876 | ||
1795 | call->type_local = call_type; | 1877 | *local = csettings; |
1796 | 1878 | ||
1797 | MSIMessage *msg_invite = msi_new_message ( TypeRequest, invite ); | 1879 | MSIMessage *msg_invite = msi_new_message ( TypeRequest, invite ); |
1798 | 1880 | ||
1799 | msi_msg_set_calltype ( msg_invite, call_type ); | 1881 | msi_msg_set_csettings ( msg_invite, local ); |
1800 | send_message ( session, call, msg_invite, call->peers[0] ); | 1882 | send_message ( session, call, msg_invite, call->peers[0] ); |
1801 | free ( msg_invite ); | 1883 | free ( msg_invite ); |
1802 | 1884 | ||
diff --git a/toxav/msi.h b/toxav/msi.h index b99b2de8..93111c9e 100644 --- a/toxav/msi.h +++ b/toxav/msi.h | |||
@@ -54,6 +54,22 @@ typedef enum { | |||
54 | } MSICallState; | 54 | } MSICallState; |
55 | 55 | ||
56 | 56 | ||
57 | /** | ||
58 | * @brief Encoding settings. | ||
59 | */ | ||
60 | typedef struct _MSICodecSettings { | ||
61 | MSICallType call_type; | ||
62 | |||
63 | uint32_t video_bitrate; /* In kbits/s */ | ||
64 | uint16_t max_video_width; /* In px */ | ||
65 | uint16_t max_video_height; /* In px */ | ||
66 | |||
67 | uint32_t audio_bitrate; /* In bits/s */ | ||
68 | uint16_t audio_frame_duration; /* In ms */ | ||
69 | uint32_t audio_sample_rate; /* In Hz */ | ||
70 | uint32_t audio_channels; | ||
71 | } MSICSettings; | ||
72 | |||
57 | 73 | ||
58 | /** | 74 | /** |
59 | * @brief Callbacks ids that handle the states | 75 | * @brief Callbacks ids that handle the states |
@@ -94,9 +110,9 @@ typedef struct _MSICall { /* Call info structure */ | |||
94 | 110 | ||
95 | MSICallState state; | 111 | MSICallState state; |
96 | 112 | ||
97 | MSICallType type_local; /* Type of payload user is ending */ | 113 | MSICSettings csettings_local; /* Local call settings */ |
98 | MSICallType *type_peer; /* Type of payload others are sending */ | 114 | MSICSettings *csettings_peer; /* Peers call settings */ |
99 | 115 | ||
100 | MSICallIDType id; /* Random value identifying the call */ | 116 | MSICallIDType id; /* Random value identifying the call */ |
101 | 117 | ||
102 | int ringing_tout_ms; /* Ringing timeout in ms */ | 118 | int ringing_tout_ms; /* Ringing timeout in ms */ |
@@ -176,7 +192,7 @@ int msi_terminate_session ( MSISession *session ); | |||
176 | * @param friend_id The friend. | 192 | * @param friend_id The friend. |
177 | * @return int | 193 | * @return int |
178 | */ | 194 | */ |
179 | int msi_invite ( MSISession *session, int32_t *call_index, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ); | 195 | int msi_invite ( MSISession* session, int32_t* call_index, MSICSettings csettings, uint32_t rngsec, uint32_t friend_id ); |
180 | 196 | ||
181 | 197 | ||
182 | /** | 198 | /** |
@@ -199,7 +215,7 @@ int msi_hangup ( MSISession *session, int32_t call_index ); | |||
199 | * @param call_type Answer with Audio or Video(both). | 215 | * @param call_type Answer with Audio or Video(both). |
200 | * @return int | 216 | * @return int |
201 | */ | 217 | */ |
202 | int msi_answer ( MSISession *session, int32_t call_index, MSICallType call_type ); | 218 | int msi_answer ( MSISession* session, int32_t call_index, MSICSettings csettings ); |
203 | 219 | ||
204 | 220 | ||
205 | /** | 221 | /** |
@@ -235,7 +251,7 @@ int msi_reject ( MSISession *session, int32_t call_index, const char *reason ); | |||
235 | * @param friend_id The friend. | 251 | * @param friend_id The friend. |
236 | * @return int | 252 | * @return int |
237 | */ | 253 | */ |
238 | int msi_change_type ( MSISession *session, int32_t call_index, MSICallType call_type ); | 254 | int msi_change_csettings ( MSISession *session, int32_t call_index, MSICSettings csettings ); |
239 | 255 | ||
240 | 256 | ||
241 | /** | 257 | /** |
diff --git a/toxav/toxav.c b/toxav/toxav.c index e15c409d..47a94fba 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -51,6 +51,24 @@ | |||
51 | /* call index invalid: true if invalid */ | 51 | /* call index invalid: true if invalid */ |
52 | #define cii(c_idx, session) (c_idx < 0 || c_idx >= session->max_calls) | 52 | #define cii(c_idx, session) (c_idx < 0 || c_idx >= session->max_calls) |
53 | 53 | ||
54 | |||
55 | const ToxAvCSettings av_DefaultSettings = { | ||
56 | TypeAudio, | ||
57 | |||
58 | 500, | ||
59 | 1280, | ||
60 | 720, | ||
61 | |||
62 | 64000, | ||
63 | 20, | ||
64 | 48000, | ||
65 | 1 | ||
66 | }; | ||
67 | |||
68 | const uint32_t av_jbufdc = 3; | ||
69 | const uint32_t av_VADd = 40; | ||
70 | |||
71 | |||
54 | static const uint8_t audio_index = 0, video_index = 1; | 72 | static const uint8_t audio_index = 0, video_index = 1; |
55 | 73 | ||
56 | typedef struct _CallSpecific { | 74 | typedef struct _CallSpecific { |
@@ -84,20 +102,39 @@ struct _ToxAv { | |||
84 | uint32_t max_calls; | 102 | uint32_t max_calls; |
85 | }; | 103 | }; |
86 | 104 | ||
87 | const ToxAvCodecSettings av_DefaultSettings = { | 105 | static MSICSettings msicsettings_cast (const ToxAvCSettings* from) |
88 | 500, | 106 | { |
89 | 1280, | 107 | MSICSettings csettings; |
90 | 720, | 108 | csettings.call_type = from->call_type; |
91 | 109 | ||
92 | 64000, | 110 | csettings.video_bitrate = from->video_bitrate; |
93 | 20, | 111 | csettings.max_video_width = from->max_video_width; |
94 | 48000, | 112 | csettings.max_video_height = from->max_video_height; |
95 | 1, | 113 | |
96 | 600, | 114 | csettings.audio_bitrate = from->audio_bitrate; |
97 | 115 | csettings.audio_frame_duration = from->audio_frame_duration; | |
98 | 3 | 116 | csettings.audio_sample_rate = from->audio_sample_rate; |
99 | }; | 117 | csettings.audio_channels = from->audio_channels; |
118 | |||
119 | return csettings; | ||
120 | } | ||
100 | 121 | ||
122 | static ToxAvCSettings toxavcsettings_cast (const MSICSettings* from) | ||
123 | { | ||
124 | ToxAvCSettings csettings; | ||
125 | csettings.call_type = from->call_type; | ||
126 | |||
127 | csettings.video_bitrate = from->video_bitrate; | ||
128 | csettings.max_video_width = from->max_video_width; | ||
129 | csettings.max_video_height = from->max_video_height; | ||
130 | |||
131 | csettings.audio_bitrate = from->audio_bitrate; | ||
132 | csettings.audio_frame_duration = from->audio_frame_duration; | ||
133 | csettings.audio_sample_rate = from->audio_sample_rate; | ||
134 | csettings.audio_channels = from->audio_channels; | ||
135 | |||
136 | return csettings; | ||
137 | } | ||
101 | 138 | ||
102 | /** | 139 | /** |
103 | * @brief Start new A/V session. There can only be one session at the time. If you register more | 140 | * @brief Start new A/V session. There can only be one session at the time. If you register more |
@@ -205,9 +242,9 @@ void toxav_register_video_recv_callback (ToxAv *av, void (*callback)(ToxAv *, in | |||
205 | * @retval 0 Success. | 242 | * @retval 0 Success. |
206 | * @retval ToxAvError On error. | 243 | * @retval ToxAvError On error. |
207 | */ | 244 | */ |
208 | int toxav_call (ToxAv *av, int32_t *call_index, int user, ToxAvCallType call_type, int ringing_seconds ) | 245 | int toxav_call (ToxAv* av, int32_t* call_index, int user, const ToxAvCSettings* csettings, int ringing_seconds ) |
209 | { | 246 | { |
210 | return msi_invite(av->msi_session, call_index, call_type, ringing_seconds * 1000, user); | 247 | return msi_invite(av->msi_session, call_index, msicsettings_cast(csettings), ringing_seconds * 1000, user); |
211 | } | 248 | } |
212 | 249 | ||
213 | /** | 250 | /** |
@@ -240,7 +277,7 @@ int toxav_hangup ( ToxAv *av, int32_t call_index ) | |||
240 | * @retval 0 Success. | 277 | * @retval 0 Success. |
241 | * @retval ToxAvError On error. | 278 | * @retval ToxAvError On error. |
242 | */ | 279 | */ |
243 | int toxav_answer ( ToxAv *av, int32_t call_index, ToxAvCallType call_type ) | 280 | int toxav_answer ( ToxAv* av, int32_t call_index, const ToxAvCSettings* csettings ) |
244 | { | 281 | { |
245 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { | 282 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { |
246 | return ErrorNoCall; | 283 | return ErrorNoCall; |
@@ -249,8 +286,8 @@ int toxav_answer ( ToxAv *av, int32_t call_index, ToxAvCallType call_type ) | |||
249 | if ( av->msi_session->calls[call_index]->state != call_starting ) { | 286 | if ( av->msi_session->calls[call_index]->state != call_starting ) { |
250 | return ErrorInvalidState; | 287 | return ErrorInvalidState; |
251 | } | 288 | } |
252 | 289 | ||
253 | return msi_answer(av->msi_session, call_index, call_type); | 290 | return msi_answer(av->msi_session, call_index, msicsettings_cast(csettings)); |
254 | } | 291 | } |
255 | 292 | ||
256 | /** | 293 | /** |
@@ -307,13 +344,13 @@ int toxav_cancel ( ToxAv *av, int32_t call_index, int peer_id, const char *reaso | |||
307 | * @retval 0 Success. | 344 | * @retval 0 Success. |
308 | * @retval ToxAvError On error. | 345 | * @retval ToxAvError On error. |
309 | */ | 346 | */ |
310 | int toxav_change_type(ToxAv *av, int32_t call_index, ToxAvCallType call_type) | 347 | int toxav_change_settings(ToxAv* av, int32_t call_index, const ToxAvCSettings* csettings) |
311 | { | 348 | { |
312 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { | 349 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { |
313 | return ErrorNoCall; | 350 | return ErrorNoCall; |
314 | } | 351 | } |
315 | 352 | ||
316 | return msi_change_type(av->msi_session, call_index, call_type); | 353 | return msi_change_csettings(av->msi_session, call_index, msicsettings_cast(csettings)); |
317 | } | 354 | } |
318 | 355 | ||
319 | /** | 356 | /** |
@@ -341,10 +378,11 @@ int toxav_stop_call ( ToxAv *av, int32_t call_index ) | |||
341 | * @retval 0 Success. | 378 | * @retval 0 Success. |
342 | * @retval ToxAvError On error. | 379 | * @retval ToxAvError On error. |
343 | */ | 380 | */ |
344 | int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettings *codec_settings, int support_video ) | 381 | int toxav_prepare_transmission ( ToxAv* av, int32_t call_index, uint32_t jbuf_capacity, uint32_t VAD_treshold, int support_video ) |
345 | { | 382 | { |
346 | if ( !av->msi_session || cii(call_index, av->msi_session) || | 383 | if ( !av->msi_session || cii(call_index, av->msi_session) || |
347 | !av->msi_session->calls[call_index] || av->calls[call_index].call_active) { | 384 | !av->msi_session->calls[call_index] || !av->msi_session->calls[call_index]->csettings_peer || |
385 | av->calls[call_index].call_active) { | ||
348 | LOGGER_ERROR("Error while starting RTP session: invalid call!\n"); | 386 | LOGGER_ERROR("Error while starting RTP session: invalid call!\n"); |
349 | return ErrorInternal; | 387 | return ErrorInternal; |
350 | } | 388 | } |
@@ -388,22 +426,42 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin | |||
388 | 426 | ||
389 | } | 427 | } |
390 | 428 | ||
391 | if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) { | 429 | if ( !(call->j_buf = create_queue(jbuf_capacity)) ) { |
392 | LOGGER_WARNING("Jitter buffer creaton failed!"); | 430 | LOGGER_WARNING("Jitter buffer creaton failed!"); |
393 | goto error; | 431 | goto error; |
394 | } | 432 | } |
395 | 433 | ||
396 | if ( (call->cs = codec_init_session(codec_settings->audio_bitrate, | 434 | ToxAvCSettings csettings = toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_peer[0]); |
397 | codec_settings->audio_frame_duration, | 435 | LOGGER_DEBUG( |
398 | codec_settings->audio_sample_rate, | 436 | "Type: %u \n" |
399 | codec_settings->audio_channels, | 437 | "Video bitrate: %u \n" |
400 | codec_settings->audio_VAD_tolerance, | 438 | "Video height: %u \n" |
401 | codec_settings->max_video_width, | 439 | "Video width: %u \n" |
402 | codec_settings->max_video_height, | 440 | "Audio bitrate: %u \n" |
403 | codec_settings->video_bitrate) )) { | 441 | "Audio framedur: %u \n" |
442 | "Audio sample rate: %u \n" | ||
443 | "Audio channels: %u \n", | ||
444 | csettings.call_type, | ||
445 | csettings.video_bitrate, | ||
446 | csettings.max_video_height, | ||
447 | csettings.max_video_width, | ||
448 | csettings.audio_bitrate, | ||
449 | csettings.audio_frame_duration, | ||
450 | csettings.audio_sample_rate, | ||
451 | csettings.audio_channels ); | ||
452 | |||
453 | if ( (call->cs = codec_init_session(csettings.audio_bitrate, | ||
454 | csettings.audio_frame_duration, | ||
455 | csettings.audio_sample_rate, | ||
456 | csettings.audio_channels, | ||
457 | VAD_treshold, | ||
458 | csettings.max_video_width, | ||
459 | csettings.max_video_height, | ||
460 | csettings.video_bitrate) )) { | ||
404 | 461 | ||
405 | if ( pthread_mutex_init(&call->mutex, NULL) != 0 ) goto error; | 462 | if ( pthread_mutex_init(&call->mutex, NULL) != 0 ) goto error; |
406 | 463 | ||
464 | LOGGER_WARNING("Got here"); | ||
407 | call->call_active = 1; | 465 | call->call_active = 1; |
408 | 466 | ||
409 | return ErrorNone; | 467 | return ErrorNone; |
@@ -701,13 +759,14 @@ inline__ int toxav_prepare_audio_frame ( ToxAv *av, int32_t call_index, uint8_t | |||
701 | * @retval ToxAvCallType On success. | 759 | * @retval ToxAvCallType On success. |
702 | * @retval ToxAvError On error. | 760 | * @retval ToxAvError On error. |
703 | */ | 761 | */ |
704 | int toxav_get_peer_transmission_type ( ToxAv *av, int32_t call_index, int peer ) | 762 | int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings* dest ) |
705 | { | 763 | { |
706 | if ( peer < 0 || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] | 764 | if ( peer < 0 || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] |
707 | || av->msi_session->calls[call_index]->peer_count <= peer ) | 765 | || av->msi_session->calls[call_index]->peer_count <= peer ) |
708 | return ErrorInternal; | 766 | return ErrorInternal; |
709 | 767 | ||
710 | return av->msi_session->calls[call_index]->type_peer[peer]; | 768 | *dest = toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_peer[peer]); |
769 | return ErrorNone; | ||
711 | } | 770 | } |
712 | 771 | ||
713 | /** | 772 | /** |
diff --git a/toxav/toxav.h b/toxav/toxav.h index 7e0a7fc2..4dfcd224 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h | |||
@@ -119,6 +119,8 @@ typedef enum { | |||
119 | * @brief Encoding settings. | 119 | * @brief Encoding settings. |
120 | */ | 120 | */ |
121 | typedef struct _ToxAvCodecSettings { | 121 | typedef struct _ToxAvCodecSettings { |
122 | ToxAvCallType call_type; | ||
123 | |||
122 | uint32_t video_bitrate; /* In kbits/s */ | 124 | uint32_t video_bitrate; /* In kbits/s */ |
123 | uint16_t max_video_width; /* In px */ | 125 | uint16_t max_video_width; /* In px */ |
124 | uint16_t max_video_height; /* In px */ | 126 | uint16_t max_video_height; /* In px */ |
@@ -127,12 +129,11 @@ typedef struct _ToxAvCodecSettings { | |||
127 | uint16_t audio_frame_duration; /* In ms */ | 129 | uint16_t audio_frame_duration; /* In ms */ |
128 | uint32_t audio_sample_rate; /* In Hz */ | 130 | uint32_t audio_sample_rate; /* In Hz */ |
129 | uint32_t audio_channels; | 131 | uint32_t audio_channels; |
130 | uint32_t audio_VAD_tolerance; /* In ms */ | 132 | } ToxAvCSettings; |
131 | 133 | ||
132 | uint32_t jbuf_capacity; /* Size of jitter buffer */ | 134 | extern const ToxAvCSettings av_DefaultSettings; |
133 | } ToxAvCodecSettings; | 135 | extern const uint32_t av_jbufdc; /* Jitter buffer default capacity */ |
134 | 136 | extern const uint32_t av_VADd; /* VAD default treshold */ | |
135 | extern const ToxAvCodecSettings av_DefaultSettings; | ||
136 | 137 | ||
137 | /** | 138 | /** |
138 | * @brief Start new A/V session. There can only be one session at the time. If you register more | 139 | * @brief Start new A/V session. There can only be one session at the time. If you register more |
@@ -194,7 +195,7 @@ void toxav_register_video_recv_callback (ToxAv *av, void (*callback)(ToxAv *, in | |||
194 | * @retval 0 Success. | 195 | * @retval 0 Success. |
195 | * @retval ToxAvError On error. | 196 | * @retval ToxAvError On error. |
196 | */ | 197 | */ |
197 | int toxav_call(ToxAv *av, int32_t *call_index, int user, ToxAvCallType call_type, int ringing_seconds); | 198 | int toxav_call(ToxAv* av, int32_t* call_index, int user, const ToxAvCSettings* csettings, int ringing_seconds); |
198 | 199 | ||
199 | /** | 200 | /** |
200 | * @brief Hangup active call. | 201 | * @brief Hangup active call. |
@@ -215,7 +216,7 @@ int toxav_hangup(ToxAv *av, int32_t call_index); | |||
215 | * @retval 0 Success. | 216 | * @retval 0 Success. |
216 | * @retval ToxAvError On error. | 217 | * @retval ToxAvError On error. |
217 | */ | 218 | */ |
218 | int toxav_answer(ToxAv *av, int32_t call_index, ToxAvCallType call_type ); | 219 | int toxav_answer(ToxAv *av, int32_t call_index, const ToxAvCSettings* csettings ); |
219 | 220 | ||
220 | /** | 221 | /** |
221 | * @brief Reject incomming call. | 222 | * @brief Reject incomming call. |
@@ -241,14 +242,14 @@ int toxav_reject(ToxAv *av, int32_t call_index, const char *reason); | |||
241 | int toxav_cancel(ToxAv *av, int32_t call_index, int peer_id, const char *reason); | 242 | int toxav_cancel(ToxAv *av, int32_t call_index, int peer_id, const char *reason); |
242 | 243 | ||
243 | /** | 244 | /** |
244 | * @brief Notify peer that we are changing call type | 245 | * @brief Notify peer that we are changing call settings |
245 | * | 246 | * |
246 | * @param av Handler. | 247 | * @param av Handler. |
247 | * @return int | 248 | * @return int |
248 | * @retval 0 Success. | 249 | * @retval 0 Success. |
249 | * @retval ToxAvError On error. | 250 | * @retval ToxAvError On error. |
250 | */ | 251 | */ |
251 | int toxav_change_type(ToxAv *av, int32_t call_index, ToxAvCallType call_type); | 252 | int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCSettings* csettings); |
252 | 253 | ||
253 | /** | 254 | /** |
254 | * @brief Terminate transmission. Note that transmission will be terminated without informing remote peer. | 255 | * @brief Terminate transmission. Note that transmission will be terminated without informing remote peer. |
@@ -269,7 +270,7 @@ int toxav_stop_call(ToxAv *av, int32_t call_index); | |||
269 | * @retval 0 Success. | 270 | * @retval 0 Success. |
270 | * @retval ToxAvError On error. | 271 | * @retval ToxAvError On error. |
271 | */ | 272 | */ |
272 | int toxav_prepare_transmission(ToxAv *av, int32_t call_index, ToxAvCodecSettings *codec_settings, int support_video); | 273 | int toxav_prepare_transmission(ToxAv *av, int32_t call_index, uint32_t jbuf_size, uint32_t VAD_treshold, int support_video); |
273 | 274 | ||
274 | /** | 275 | /** |
275 | * @brief Call this at the end of the transmission. | 276 | * @brief Call this at the end of the transmission. |
@@ -343,7 +344,7 @@ int toxav_prepare_audio_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, in | |||
343 | * @retval ToxAvCallType On success. | 344 | * @retval ToxAvCallType On success. |
344 | * @retval ToxAvError On error. | 345 | * @retval ToxAvError On error. |
345 | */ | 346 | */ |
346 | int toxav_get_peer_transmission_type ( ToxAv *av, int32_t call_index, int peer ); | 347 | int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings* dest ); |
347 | 348 | ||
348 | /** | 349 | /** |
349 | * @brief Get id of peer participating in conversation | 350 | * @brief Get id of peer participating in conversation |
@@ -374,26 +375,6 @@ ToxAvCallState toxav_get_call_state ( ToxAv *av, int32_t call_index ); | |||
374 | */ | 375 | */ |
375 | int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCapabilities capability ); | 376 | int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCapabilities capability ); |
376 | 377 | ||
377 | /** | ||
378 | * @brief Set queue limit | ||
379 | * | ||
380 | * @param av Handler | ||
381 | * @param call_index index | ||
382 | * @param limit the limit | ||
383 | * @return void | ||
384 | */ | ||
385 | int toxav_set_audio_queue_limit ( ToxAv *av, int32_t call_index, uint64_t limit ); | ||
386 | |||
387 | /** | ||
388 | * @brief Set queue limit | ||
389 | * | ||
390 | * @param av Handler | ||
391 | * @param call_index index | ||
392 | * @param limit the limit | ||
393 | * @return void | ||
394 | */ | ||
395 | int toxav_set_video_queue_limit ( ToxAv *av, int32_t call_index, uint64_t limit ); | ||
396 | |||
397 | 378 | ||
398 | Tox *toxav_get_tox(ToxAv *av); | 379 | Tox *toxav_get_tox(ToxAv *av); |
399 | 380 | ||