summaryrefslogtreecommitdiff
path: root/toxav/toxav.c
diff options
context:
space:
mode:
authorGregory Mullen (grayhatter) <greg@grayhatter.com>2016-09-11 16:27:03 -0700
committerGregory Mullen (grayhatter) <greg@grayhatter.com>2016-09-17 14:05:51 -0700
commit21f8db12c45bd56293262cd4abfb73cd9abec821 (patch)
tree580729367d00e1eb7e0c4d533777d22af7d7ffc5 /toxav/toxav.c
parent5da85c582d97d746887da407153afc0acf0a4215 (diff)
Make ToxAV stateless
Diffstat (limited to 'toxav/toxav.c')
-rw-r--r--toxav/toxav.c124
1 files changed, 63 insertions, 61 deletions
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 1ae914e8..29046265 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -42,10 +42,16 @@ typedef struct ToxAVCall_s {
42 ToxAV *av; 42 ToxAV *av;
43 43
44 pthread_mutex_t mutex_audio[1]; 44 pthread_mutex_t mutex_audio[1];
45 PAIR(RTPSession *, ACSession *) audio; 45 struct {
46 RTPSession *first;
47 ACSession *second;
48 } audio;
46 49
47 pthread_mutex_t mutex_video[1]; 50 pthread_mutex_t mutex_video[1];
48 PAIR(RTPSession *, VCSession *) video; 51 struct {
52 RTPSession *first;
53 VCSession *second;
54 } video;
49 55
50 BWController *bwc; 56 BWController *bwc;
51 57
@@ -75,11 +81,12 @@ struct ToxAV {
75 uint32_t calls_head; 81 uint32_t calls_head;
76 pthread_mutex_t mutex[1]; 82 pthread_mutex_t mutex[1];
77 83
78 PAIR(toxav_call_cb *, void *) ccb; /* Call callback */ 84 toxav_call_cb *on_call;
79 PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */ 85 toxav_call_state_cb *on_call_state;
80 PAIR(toxav_audio_receive_frame_cb *, void *) acb; /* Audio frame receive callback */ 86 toxav_bit_rate_status_cb *on_bit_rate_status_change;
81 PAIR(toxav_video_receive_frame_cb *, void *) vcb; /* Video frame receive callback */ 87
82 PAIR(toxav_bit_rate_status_cb *, void *) bcb; /* Bit rate control callback */ 88 toxav_audio_receive_frame_cb *on_audio_frame;
89 toxav_video_receive_frame_cb *on_video_frame;
83 90
84 /** Decode time measures */ 91 /** Decode time measures */
85 int32_t dmssc; /** Measure count */ 92 int32_t dmssc; /** Measure count */
@@ -89,17 +96,17 @@ struct ToxAV {
89 uint32_t interval; /** Calculated interval */ 96 uint32_t interval; /** Calculated interval */
90}; 97};
91 98
92void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *user_data); 99void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *call_data, void *userdata);
93 100
94int callback_invite(void *toxav_inst, MSICall *call); 101int callback_invite(void *toxav_inst, MSICall *call, void *userdata);
95int callback_start(void *toxav_inst, MSICall *call); 102int callback_start(void *toxav_inst, MSICall *call, void *userdata);
96int callback_end(void *toxav_inst, MSICall *call); 103int callback_end(void *toxav_inst, MSICall *call, void *userdata);
97int callback_error(void *toxav_inst, MSICall *call); 104int callback_error(void *toxav_inst, MSICall *call, void *userdata);
98int callback_capabilites(void *toxav_inst, MSICall *call); 105int callback_capabilites(void *toxav_inst, MSICall *call, void *userdata);
99 106
100bool audio_bit_rate_invalid(uint32_t bit_rate); 107bool audio_bit_rate_invalid(uint32_t bit_rate);
101bool video_bit_rate_invalid(uint32_t bit_rate); 108bool video_bit_rate_invalid(uint32_t bit_rate);
102bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t state); 109bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t state, void *userdata);
103ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, TOXAV_ERR_CALL *error); 110ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, TOXAV_ERR_CALL *error);
104ToxAVCall *call_get(ToxAV *av, uint32_t friend_number); 111ToxAVCall *call_get(ToxAV *av, uint32_t friend_number);
105ToxAVCall *call_remove(ToxAVCall *call); 112ToxAVCall *call_remove(ToxAVCall *call);
@@ -230,7 +237,7 @@ uint32_t toxav_iteration_interval(const ToxAV *av)
230 /* If no call is active interval is 200 */ 237 /* If no call is active interval is 200 */
231 return av->calls ? av->interval : 200; 238 return av->calls ? av->interval : 200;
232} 239}
233void toxav_iterate(ToxAV *av) 240void toxav_iterate(ToxAV *av, void *userdata)
234{ 241{
235 pthread_mutex_lock(av->mutex); 242 pthread_mutex_lock(av->mutex);
236 243
@@ -249,8 +256,8 @@ void toxav_iterate(ToxAV *av)
249 pthread_mutex_lock(i->mutex); 256 pthread_mutex_lock(i->mutex);
250 pthread_mutex_unlock(av->mutex); 257 pthread_mutex_unlock(av->mutex);
251 258
252 ac_iterate(i->audio.second); 259 ac_iterate(i->audio.second, userdata);
253 vc_iterate(i->video.second); 260 vc_iterate(i->video.second, userdata);
254 261
255 if (i->msi_call->self_capabilities & msi_CapRAudio && 262 if (i->msi_call->self_capabilities & msi_CapRAudio &&
256 i->msi_call->peer_capabilities & msi_CapSAudio) { 263 i->msi_call->peer_capabilities & msi_CapSAudio) {
@@ -329,11 +336,10 @@ END:
329 336
330 return rc == TOXAV_ERR_CALL_OK; 337 return rc == TOXAV_ERR_CALL_OK;
331} 338}
332void toxav_callback_call(ToxAV *av, toxav_call_cb *callback, void *user_data) 339void toxav_callback_call(ToxAV *av, toxav_call_cb *callback)
333{ 340{
334 pthread_mutex_lock(av->mutex); 341 pthread_mutex_lock(av->mutex);
335 av->ccb.first = callback; 342 av->on_call = callback;
336 av->ccb.second = user_data;
337 pthread_mutex_unlock(av->mutex); 343 pthread_mutex_unlock(av->mutex);
338} 344}
339bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, 345bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate,
@@ -388,11 +394,10 @@ END:
388 394
389 return rc == TOXAV_ERR_ANSWER_OK; 395 return rc == TOXAV_ERR_ANSWER_OK;
390} 396}
391void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *callback, void *user_data) 397void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *callback)
392{ 398{
393 pthread_mutex_lock(av->mutex); 399 pthread_mutex_lock(av->mutex);
394 av->scb.first = callback; 400 av->on_call_state = callback;
395 av->scb.second = user_data;
396 pthread_mutex_unlock(av->mutex); 401 pthread_mutex_unlock(av->mutex);
397} 402}
398bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error) 403bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error)
@@ -664,11 +669,10 @@ END:
664 669
665 return rc == TOXAV_ERR_BIT_RATE_SET_OK; 670 return rc == TOXAV_ERR_BIT_RATE_SET_OK;
666} 671}
667void toxav_callback_bit_rate_status(ToxAV *av, toxav_bit_rate_status_cb *callback, void *user_data) 672void toxav_callback_bit_rate_status(ToxAV *av, toxav_bit_rate_status_cb *callback)
668{ 673{
669 pthread_mutex_lock(av->mutex); 674 pthread_mutex_lock(av->mutex);
670 av->bcb.first = callback; 675 av->on_bit_rate_status_change = callback;
671 av->bcb.second = user_data;
672 pthread_mutex_unlock(av->mutex); 676 pthread_mutex_unlock(av->mutex);
673} 677}
674bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pcm, size_t sample_count, 678bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pcm, size_t sample_count,
@@ -856,18 +860,16 @@ END:
856 860
857 return rc == TOXAV_ERR_SEND_FRAME_OK; 861 return rc == TOXAV_ERR_SEND_FRAME_OK;
858} 862}
859void toxav_callback_audio_receive_frame(ToxAV *av, toxav_audio_receive_frame_cb *callback, void *user_data) 863void toxav_callback_audio_receive_frame(ToxAV *av, toxav_audio_receive_frame_cb *callback)
860{ 864{
861 pthread_mutex_lock(av->mutex); 865 pthread_mutex_lock(av->mutex);
862 av->acb.first = callback; 866 av->on_audio_frame = callback;
863 av->acb.second = user_data;
864 pthread_mutex_unlock(av->mutex); 867 pthread_mutex_unlock(av->mutex);
865} 868}
866void toxav_callback_video_receive_frame(ToxAV *av, toxav_video_receive_frame_cb *callback, void *user_data) 869void toxav_callback_video_receive_frame(ToxAV *av, toxav_video_receive_frame_cb *callback)
867{ 870{
868 pthread_mutex_lock(av->mutex); 871 pthread_mutex_lock(av->mutex);
869 av->vcb.first = callback; 872 av->on_video_frame = callback;
870 av->vcb.second = user_data;
871 pthread_mutex_unlock(av->mutex); 873 pthread_mutex_unlock(av->mutex);
872} 874}
873 875
@@ -877,7 +879,7 @@ void toxav_callback_video_receive_frame(ToxAV *av, toxav_video_receive_frame_cb
877 * :: Internal 879 * :: Internal
878 * 880 *
879 ******************************************************************************/ 881 ******************************************************************************/
880void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *user_data) 882void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *call_data, void *userdata)
881{ 883{
882 /* Callback which is called when the internal measure mechanism reported packet loss. 884 /* Callback which is called when the internal measure mechanism reported packet loss.
883 * We report suggested lowered bitrate to an app. If app is sending both audio and video, 885 * We report suggested lowered bitrate to an app. If app is sending both audio and video,
@@ -886,7 +888,7 @@ void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *u
886 * The application may choose to disable video totally if the stream is too bad. 888 * The application may choose to disable video totally if the stream is too bad.
887 */ 889 */
888 890
889 ToxAVCall *call = user_data; 891 ToxAVCall *call = call_data;
890 assert(call); 892 assert(call);
891 893
892 LOGGER_DEBUG(call->av->m->log, "Reported loss of %f%%", loss * 100); 894 LOGGER_DEBUG(call->av->m->log, "Reported loss of %f%%", loss * 100);
@@ -897,25 +899,25 @@ void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *u
897 899
898 pthread_mutex_lock(call->av->mutex); 900 pthread_mutex_lock(call->av->mutex);
899 901
900 if (!call->av->bcb.first) { 902 if (!call->av->on_bit_rate_status_change) {
901 pthread_mutex_unlock(call->av->mutex); 903 pthread_mutex_unlock(call->av->mutex);
902 LOGGER_WARNING(call->av->m->log, "No callback to report loss on"); 904 LOGGER_WARNING(call->av->m->log, "No callback to report loss on");
903 return; 905 return;
904 } 906 }
905 907
906 if (call->video_bit_rate) { 908 if (call->video_bit_rate) {
907 (*call->av->bcb.first)(call->av, friend_number, call->audio_bit_rate, 909 (*call->av->on_bit_rate_status_change)(call->av, friend_number, call->audio_bit_rate,
908 call->video_bit_rate - (call->video_bit_rate * loss), 910 call->video_bit_rate - (call->video_bit_rate * loss),
909 call->av->bcb.second); 911 userdata);
910 } else if (call->audio_bit_rate) { 912 } else if (call->audio_bit_rate) {
911 (*call->av->bcb.first)(call->av, friend_number, 913 (*call->av->on_bit_rate_status_change)(call->av, friend_number,
912 call->audio_bit_rate - (call->audio_bit_rate * loss), 914 call->audio_bit_rate - (call->audio_bit_rate * loss),
913 0, call->av->bcb.second); 915 0, userdata);
914 } 916 }
915 917
916 pthread_mutex_unlock(call->av->mutex); 918 pthread_mutex_unlock(call->av->mutex);
917} 919}
918int callback_invite(void *toxav_inst, MSICall *call) 920int callback_invite(void *toxav_inst, MSICall *call, void *userdata)
919{ 921{
920 ToxAV *toxav = toxav_inst; 922 ToxAV *toxav = toxav_inst;
921 pthread_mutex_lock(toxav->mutex); 923 pthread_mutex_lock(toxav->mutex);
@@ -931,9 +933,9 @@ int callback_invite(void *toxav_inst, MSICall *call)
931 call->av_call = av_call; 933 call->av_call = av_call;
932 av_call->msi_call = call; 934 av_call->msi_call = call;
933 935
934 if (toxav->ccb.first) { 936 if (toxav->on_call) {
935 toxav->ccb.first(toxav, call->friend_number, call->peer_capabilities & msi_CapSAudio, 937 toxav->on_call(toxav, call->friend_number, call->peer_capabilities & msi_CapSAudio,
936 call->peer_capabilities & msi_CapSVideo, toxav->ccb.second); 938 call->peer_capabilities & msi_CapSVideo, userdata);
937 } else { 939 } else {
938 /* No handler to capture the call request, send failure */ 940 /* No handler to capture the call request, send failure */
939 pthread_mutex_unlock(toxav->mutex); 941 pthread_mutex_unlock(toxav->mutex);
@@ -943,7 +945,7 @@ int callback_invite(void *toxav_inst, MSICall *call)
943 pthread_mutex_unlock(toxav->mutex); 945 pthread_mutex_unlock(toxav->mutex);
944 return 0; 946 return 0;
945} 947}
946int callback_start(void *toxav_inst, MSICall *call) 948int callback_start(void *toxav_inst, MSICall *call, void *userdata)
947{ 949{
948 ToxAV *toxav = toxav_inst; 950 ToxAV *toxav = toxav_inst;
949 pthread_mutex_lock(toxav->mutex); 951 pthread_mutex_lock(toxav->mutex);
@@ -957,13 +959,13 @@ int callback_start(void *toxav_inst, MSICall *call)
957 } 959 }
958 960
959 if (!call_prepare_transmission(av_call)) { 961 if (!call_prepare_transmission(av_call)) {
960 callback_error(toxav_inst, call); 962 callback_error(toxav_inst, call, userdata);
961 pthread_mutex_unlock(toxav->mutex); 963 pthread_mutex_unlock(toxav->mutex);
962 return -1; 964 return -1;
963 } 965 }
964 966
965 if (!invoke_call_state_callback(toxav, call->friend_number, call->peer_capabilities)) { 967 if (!invoke_call_state_callback(toxav, call->friend_number, call->peer_capabilities, userdata)) {
966 callback_error(toxav_inst, call); 968 callback_error(toxav_inst, call, userdata);
967 pthread_mutex_unlock(toxav->mutex); 969 pthread_mutex_unlock(toxav->mutex);
968 return -1; 970 return -1;
969 } 971 }
@@ -971,12 +973,12 @@ int callback_start(void *toxav_inst, MSICall *call)
971 pthread_mutex_unlock(toxav->mutex); 973 pthread_mutex_unlock(toxav->mutex);
972 return 0; 974 return 0;
973} 975}
974int callback_end(void *toxav_inst, MSICall *call) 976int callback_end(void *toxav_inst, MSICall *call, void *userdata)
975{ 977{
976 ToxAV *toxav = toxav_inst; 978 ToxAV *toxav = toxav_inst;
977 pthread_mutex_lock(toxav->mutex); 979 pthread_mutex_lock(toxav->mutex);
978 980
979 invoke_call_state_callback(toxav, call->friend_number, TOXAV_FRIEND_CALL_STATE_FINISHED); 981 invoke_call_state_callback(toxav, call->friend_number, TOXAV_FRIEND_CALL_STATE_FINISHED, userdata);
980 982
981 if (call->av_call) { 983 if (call->av_call) {
982 call_kill_transmission(call->av_call); 984 call_kill_transmission(call->av_call);
@@ -986,12 +988,12 @@ int callback_end(void *toxav_inst, MSICall *call)
986 pthread_mutex_unlock(toxav->mutex); 988 pthread_mutex_unlock(toxav->mutex);
987 return 0; 989 return 0;
988} 990}
989int callback_error(void *toxav_inst, MSICall *call) 991int callback_error(void *toxav_inst, MSICall *call, void *userdata)
990{ 992{
991 ToxAV *toxav = toxav_inst; 993 ToxAV *toxav = toxav_inst;
992 pthread_mutex_lock(toxav->mutex); 994 pthread_mutex_lock(toxav->mutex);
993 995
994 invoke_call_state_callback(toxav, call->friend_number, TOXAV_FRIEND_CALL_STATE_ERROR); 996 invoke_call_state_callback(toxav, call->friend_number, TOXAV_FRIEND_CALL_STATE_ERROR, userdata);
995 997
996 if (call->av_call) { 998 if (call->av_call) {
997 call_kill_transmission(call->av_call); 999 call_kill_transmission(call->av_call);
@@ -1001,7 +1003,7 @@ int callback_error(void *toxav_inst, MSICall *call)
1001 pthread_mutex_unlock(toxav->mutex); 1003 pthread_mutex_unlock(toxav->mutex);
1002 return 0; 1004 return 0;
1003} 1005}
1004int callback_capabilites(void *toxav_inst, MSICall *call) 1006int callback_capabilites(void *toxav_inst, MSICall *call, void *userdata)
1005{ 1007{
1006 ToxAV *toxav = toxav_inst; 1008 ToxAV *toxav = toxav_inst;
1007 pthread_mutex_lock(toxav->mutex); 1009 pthread_mutex_lock(toxav->mutex);
@@ -1018,7 +1020,7 @@ int callback_capabilites(void *toxav_inst, MSICall *call)
1018 rtp_stop_receiving(((ToxAVCall *)call->av_call)->video.first); 1020 rtp_stop_receiving(((ToxAVCall *)call->av_call)->video.first);
1019 } 1021 }
1020 1022
1021 invoke_call_state_callback(toxav, call->friend_number, call->peer_capabilities); 1023 invoke_call_state_callback(toxav, call->friend_number, call->peer_capabilities, userdata);
1022 1024
1023 pthread_mutex_unlock(toxav->mutex); 1025 pthread_mutex_unlock(toxav->mutex);
1024 return 0; 1026 return 0;
@@ -1036,10 +1038,10 @@ bool video_bit_rate_invalid(uint32_t bit_rate)
1036 /* TODO(mannol): If anyone knows the answer to this one please fill it up */ 1038 /* TODO(mannol): If anyone knows the answer to this one please fill it up */
1037 return false; 1039 return false;
1038} 1040}
1039bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t state) 1041bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t state, void *userdata)
1040{ 1042{
1041 if (av->scb.first) { 1043 if (av->on_call_state) {
1042 av->scb.first(av, friend_number, state, av->scb.second); 1044 av->on_call_state(av, friend_number, state, userdata);
1043 } else { 1045 } else {
1044 return false; 1046 return false;
1045 } 1047 }
@@ -1194,7 +1196,7 @@ bool call_prepare_transmission(ToxAVCall *call)
1194 1196
1195 ToxAV *av = call->av; 1197 ToxAV *av = call->av;
1196 1198
1197 if (!av->acb.first && !av->vcb.first) { 1199 if (!av->on_audio_frame && !av->on_video_frame) {
1198 /* It makes no sense to have CSession without callbacks */ 1200 /* It makes no sense to have CSession without callbacks */
1199 return false; 1201 return false;
1200 } 1202 }
@@ -1220,7 +1222,7 @@ bool call_prepare_transmission(ToxAVCall *call)
1220 call->bwc = bwc_new(av->m, call->friend_number, callback_bwc, call); 1222 call->bwc = bwc_new(av->m, call->friend_number, callback_bwc, call);
1221 1223
1222 { /* Prepare audio */ 1224 { /* Prepare audio */
1223 call->audio.second = ac_new(av->m->log, av, call->friend_number, av->acb.first, av->acb.second); 1225 call->audio.second = ac_new(av->m->log, av, call->friend_number, av->on_audio_frame);
1224 1226
1225 if (!call->audio.second) { 1227 if (!call->audio.second) {
1226 LOGGER_ERROR(av->m->log, "Failed to create audio codec session"); 1228 LOGGER_ERROR(av->m->log, "Failed to create audio codec session");
@@ -1236,7 +1238,7 @@ bool call_prepare_transmission(ToxAVCall *call)
1236 } 1238 }
1237 } 1239 }
1238 { /* Prepare video */ 1240 { /* Prepare video */
1239 call->video.second = vc_new(av->m->log, av, call->friend_number, av->vcb.first, av->vcb.second); 1241 call->video.second = vc_new(av->m->log, av, call->friend_number, av->on_video_frame);
1240 1242
1241 if (!call->video.second) { 1243 if (!call->video.second) {
1242 LOGGER_ERROR(av->m->log, "Failed to create video codec session"); 1244 LOGGER_ERROR(av->m->log, "Failed to create video codec session");