diff options
Diffstat (limited to 'toxav/toxav.c')
-rw-r--r-- | toxav/toxav.c | 300 |
1 files changed, 169 insertions, 131 deletions
diff --git a/toxav/toxav.c b/toxav/toxav.c index e6b51ee4..78243ae6 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -40,15 +40,16 @@ enum { | |||
40 | video_index, | 40 | video_index, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | typedef struct ToxAVCall_s | 43 | typedef struct ToxAVCall_s { |
44 | { | ||
45 | ToxAV* av; | 44 | ToxAV* av; |
46 | pthread_mutex_t mutex_control[1]; | ||
47 | pthread_mutex_t mutex_encoding_audio[1]; | ||
48 | pthread_mutex_t mutex_encoding_video[1]; | ||
49 | pthread_mutex_t mutex_do[1]; | ||
50 | RTPSession *rtps[2]; /* Audio is first and video is second */ | 45 | RTPSession *rtps[2]; /* Audio is first and video is second */ |
51 | CSSession *cs; | 46 | CSSession *cs; |
47 | |||
48 | pthread_mutex_t mutex_audio_sending[1]; | ||
49 | pthread_mutex_t mutex_video_sending[1]; | ||
50 | /* Only audio or video can be decoded at one time */ | ||
51 | pthread_mutex_t mutex_decoding[1]; | ||
52 | |||
52 | bool active; | 53 | bool active; |
53 | MSICall* msi_call; | 54 | MSICall* msi_call; |
54 | uint32_t friend_id; | 55 | uint32_t friend_id; |
@@ -56,14 +57,14 @@ typedef struct ToxAVCall_s | |||
56 | uint32_t s_audio_b; /* Sending audio bitrate */ | 57 | uint32_t s_audio_b; /* Sending audio bitrate */ |
57 | uint32_t s_video_b; /* Sending video bitrate */ | 58 | uint32_t s_video_b; /* Sending video bitrate */ |
58 | 59 | ||
59 | uint8_t last_capabilities; | 60 | uint8_t last_self_capabilities; |
61 | uint8_t last_peer_capabilities; | ||
60 | 62 | ||
61 | struct ToxAVCall_s *prev; | 63 | struct ToxAVCall_s *prev; |
62 | struct ToxAVCall_s *next; | 64 | struct ToxAVCall_s *next; |
63 | } ToxAVCall; | 65 | } ToxAVCall; |
64 | 66 | ||
65 | struct toxAV | 67 | struct toxAV { |
66 | { | ||
67 | Messenger* m; | 68 | Messenger* m; |
68 | MSISession* msi; | 69 | MSISession* msi; |
69 | 70 | ||
@@ -71,11 +72,14 @@ struct toxAV | |||
71 | ToxAVCall** calls; | 72 | ToxAVCall** calls; |
72 | uint32_t calls_tail; | 73 | uint32_t calls_tail; |
73 | uint32_t calls_head; | 74 | uint32_t calls_head; |
75 | pthread_mutex_t mutex[1]; | ||
74 | 76 | ||
75 | PAIR(toxav_call_cb *, void*) ccb; /* Call callback */ | 77 | PAIR(toxav_call_cb *, void*) ccb; /* Call callback */ |
76 | PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */ | 78 | PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */ |
77 | PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ | 79 | PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ |
78 | PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ | 80 | PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ |
81 | PAIR(toxav_request_video_frame_cb *, void *) rvcb; /* Request video callback */ | ||
82 | PAIR(toxav_request_audio_frame_cb *, void *) racb; /* Request video callback */ | ||
79 | 83 | ||
80 | /** Decode time measures */ | 84 | /** Decode time measures */ |
81 | int32_t dmssc; /** Measure count */ | 85 | int32_t dmssc; /** Measure count */ |
@@ -92,7 +96,6 @@ int callback_end(void* toxav_inst, MSICall* call); | |||
92 | int callback_error(void* toxav_inst, MSICall* call); | 96 | int callback_error(void* toxav_inst, MSICall* call); |
93 | int callback_capabilites(void* toxav_inst, MSICall* call); | 97 | int callback_capabilites(void* toxav_inst, MSICall* call); |
94 | 98 | ||
95 | TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities); | ||
96 | ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error); | 99 | ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error); |
97 | ToxAVCall* call_get(ToxAV* av, uint32_t friend_number); | 100 | ToxAVCall* call_get(ToxAV* av, uint32_t friend_number); |
98 | void call_remove(ToxAVCall* call); | 101 | void call_remove(ToxAVCall* call); |
@@ -118,7 +121,7 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error) | |||
118 | goto FAILURE; | 121 | goto FAILURE; |
119 | } | 122 | } |
120 | 123 | ||
121 | av = calloc ( sizeof(ToxAV), 1); | 124 | av = calloc (sizeof(ToxAV), 1); |
122 | 125 | ||
123 | if (av == NULL) { | 126 | if (av == NULL) { |
124 | LOGGER_WARNING("Allocation failed!"); | 127 | LOGGER_WARNING("Allocation failed!"); |
@@ -126,10 +129,17 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error) | |||
126 | goto FAILURE; | 129 | goto FAILURE; |
127 | } | 130 | } |
128 | 131 | ||
132 | if (create_recursive_mutex(av->mutex) == -1) { | ||
133 | LOGGER_WARNING("Mutex creation failed!"); | ||
134 | rc = TOXAV_ERR_NEW_MALLOC; | ||
135 | goto FAILURE; | ||
136 | } | ||
137 | |||
129 | av->m = (Messenger *)tox; | 138 | av->m = (Messenger *)tox; |
130 | av->msi = msi_new(av->m); | 139 | av->msi = msi_new(av->m); |
131 | 140 | ||
132 | if (av->msi == NULL) { | 141 | if (av->msi == NULL) { |
142 | pthread_mutex_destroy(av->mutex); | ||
133 | rc = TOXAV_ERR_NEW_MALLOC; | 143 | rc = TOXAV_ERR_NEW_MALLOC; |
134 | goto FAILURE; | 144 | goto FAILURE; |
135 | } | 145 | } |
@@ -163,6 +173,7 @@ void toxav_kill(ToxAV* av) | |||
163 | { | 173 | { |
164 | if (av == NULL) | 174 | if (av == NULL) |
165 | return; | 175 | return; |
176 | pthread_mutex_lock(av->mutex); | ||
166 | 177 | ||
167 | msi_kill(av->msi); | 178 | msi_kill(av->msi); |
168 | 179 | ||
@@ -175,6 +186,8 @@ void toxav_kill(ToxAV* av) | |||
175 | } | 186 | } |
176 | } | 187 | } |
177 | 188 | ||
189 | pthread_mutex_unlock(av->mutex); | ||
190 | pthread_mutex_destroy(av->mutex); | ||
178 | free(av); | 191 | free(av); |
179 | } | 192 | } |
180 | 193 | ||
@@ -185,6 +198,7 @@ Tox* toxav_get_tox(ToxAV* av) | |||
185 | 198 | ||
186 | uint32_t toxav_iteration_interval(const ToxAV* av) | 199 | uint32_t toxav_iteration_interval(const ToxAV* av) |
187 | { | 200 | { |
201 | /* If no call is active interval is 200 */ | ||
188 | return av->calls ? av->interval : 200; | 202 | return av->calls ? av->interval : 200; |
189 | } | 203 | } |
190 | 204 | ||
@@ -194,14 +208,28 @@ void toxav_iteration(ToxAV* av) | |||
194 | return; | 208 | return; |
195 | 209 | ||
196 | uint64_t start = current_time_monotonic(); | 210 | uint64_t start = current_time_monotonic(); |
197 | uint32_t rc = 200 + av->dmssa; /* If no call is active interval is 200 */ | 211 | uint32_t rc = 0; |
198 | 212 | ||
213 | pthread_mutex_lock(av->mutex); | ||
199 | ToxAVCall* i = av->calls[av->calls_head]; | 214 | ToxAVCall* i = av->calls[av->calls_head]; |
200 | for (; i; i = i->next) { | 215 | for (; i; i = i->next) { |
201 | if (i->active) { | 216 | if (i->active) { |
217 | pthread_mutex_lock(i->mutex_decoding); | ||
218 | |||
219 | /* TODO make AV synchronisation */ | ||
220 | if (av->racb.first) | ||
221 | av->racb.first(av, i->friend_id, av->racb.second); | ||
222 | if (av->rvcb.first) | ||
223 | av->rvcb.first(av, i->friend_id, av->rvcb.second); | ||
224 | |||
225 | pthread_mutex_unlock(av->mutex); | ||
202 | cs_do(i->cs); | 226 | cs_do(i->cs); |
203 | rc = MIN(i->cs->last_packet_frame_duration, rc); | 227 | rc = MIN(i->cs->last_packet_frame_duration, rc); |
204 | } | 228 | pthread_mutex_unlock(i->mutex_decoding); |
229 | } else | ||
230 | continue; | ||
231 | |||
232 | pthread_mutex_lock(av->mutex); | ||
205 | } | 233 | } |
206 | 234 | ||
207 | av->interval = rc < av->dmssa ? 0 : rc - av->dmssa; | 235 | av->interval = rc < av->dmssa ? 0 : rc - av->dmssa; |
@@ -216,38 +244,47 @@ void toxav_iteration(ToxAV* av) | |||
216 | 244 | ||
217 | bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error) | 245 | bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error) |
218 | { | 246 | { |
247 | pthread_mutex_lock(av->mutex); | ||
219 | ToxAVCall* call = call_new(av, friend_number, error); | 248 | ToxAVCall* call = call_new(av, friend_number, error); |
220 | if (call == NULL) | 249 | if (call == NULL) { |
250 | pthread_mutex_unlock(av->mutex); | ||
221 | return false; | 251 | return false; |
252 | } | ||
222 | 253 | ||
223 | call->s_audio_b = audio_bit_rate; | 254 | call->s_audio_b = audio_bit_rate; |
224 | call->s_video_b = video_bit_rate; | 255 | call->s_video_b = video_bit_rate; |
225 | 256 | ||
226 | call->last_capabilities = msi_CapRAudio | msi_CapRVideo; | 257 | call->last_self_capabilities = msi_CapRAudio | msi_CapRVideo; |
227 | 258 | ||
228 | call->last_capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0; | 259 | call->last_self_capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0; |
229 | call->last_capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0; | 260 | call->last_self_capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0; |
230 | 261 | ||
231 | if (msi_invite(av->msi, &call->msi_call, friend_number, call->last_capabilities) != 0) { | 262 | if (msi_invite(av->msi, &call->msi_call, friend_number, call->last_self_capabilities) != 0) { |
232 | call_remove(call); | 263 | call_remove(call); |
233 | if (error) | 264 | if (error) |
234 | *error = TOXAV_ERR_CALL_MALLOC; | 265 | *error = TOXAV_ERR_CALL_MALLOC; |
266 | pthread_mutex_unlock(av->mutex); | ||
235 | return false; | 267 | return false; |
236 | } | 268 | } |
237 | 269 | ||
238 | call->msi_call->av_call = call; | 270 | call->msi_call->av_call = call; |
271 | pthread_mutex_unlock(av->mutex); | ||
239 | 272 | ||
240 | return true; | 273 | return true; |
241 | } | 274 | } |
242 | 275 | ||
243 | void toxav_callback_call(ToxAV* av, toxav_call_cb* function, void* user_data) | 276 | void toxav_callback_call(ToxAV* av, toxav_call_cb* function, void* user_data) |
244 | { | 277 | { |
278 | pthread_mutex_lock(av->mutex); | ||
245 | av->ccb.first = function; | 279 | av->ccb.first = function; |
246 | av->ccb.second = user_data; | 280 | av->ccb.second = user_data; |
281 | pthread_mutex_unlock(av->mutex); | ||
247 | } | 282 | } |
248 | 283 | ||
249 | bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER* error) | 284 | bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER* error) |
250 | { | 285 | { |
286 | pthread_mutex_lock(av->mutex); | ||
287 | |||
251 | TOXAV_ERR_ANSWER rc = TOXAV_ERR_ANSWER_OK; | 288 | TOXAV_ERR_ANSWER rc = TOXAV_ERR_ANSWER_OK; |
252 | if (m_friend_exists(av->m, friend_number) == 0) { | 289 | if (m_friend_exists(av->m, friend_number) == 0) { |
253 | rc = TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND; | 290 | rc = TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND; |
@@ -270,16 +307,18 @@ bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, ui | |||
270 | call->s_audio_b = audio_bit_rate; | 307 | call->s_audio_b = audio_bit_rate; |
271 | call->s_video_b = video_bit_rate; | 308 | call->s_video_b = video_bit_rate; |
272 | 309 | ||
273 | call->last_capabilities = msi_CapRAudio | msi_CapRVideo; | 310 | call->last_self_capabilities = msi_CapRAudio | msi_CapRVideo; |
274 | 311 | ||
275 | call->last_capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0; | 312 | call->last_self_capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0; |
276 | call->last_capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0; | 313 | call->last_self_capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0; |
277 | 314 | ||
278 | if (msi_answer(call->msi_call, call->last_capabilities) != 0) | 315 | if (msi_answer(call->msi_call, call->last_self_capabilities) != 0) |
279 | rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING; /* the only reason for msi_answer to fail */ | 316 | rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING; /* the only reason for msi_answer to fail */ |
280 | 317 | ||
281 | 318 | ||
282 | END: | 319 | END: |
320 | pthread_mutex_unlock(av->mutex); | ||
321 | |||
283 | if (error) | 322 | if (error) |
284 | *error = rc; | 323 | *error = rc; |
285 | 324 | ||
@@ -288,12 +327,15 @@ END: | |||
288 | 327 | ||
289 | void toxav_callback_call_state(ToxAV* av, toxav_call_state_cb* function, void* user_data) | 328 | void toxav_callback_call_state(ToxAV* av, toxav_call_state_cb* function, void* user_data) |
290 | { | 329 | { |
330 | pthread_mutex_lock(av->mutex); | ||
291 | av->scb.first = function; | 331 | av->scb.first = function; |
292 | av->scb.second = user_data; | 332 | av->scb.second = user_data; |
333 | pthread_mutex_unlock(av->mutex); | ||
293 | } | 334 | } |
294 | 335 | ||
295 | bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL* error) | 336 | bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL* error) |
296 | { | 337 | { |
338 | pthread_mutex_lock(av->mutex); | ||
297 | TOXAV_ERR_CALL_CONTROL rc = TOXAV_ERR_CALL_CONTROL_OK; | 339 | TOXAV_ERR_CALL_CONTROL rc = TOXAV_ERR_CALL_CONTROL_OK; |
298 | 340 | ||
299 | if (m_friend_exists(av->m, friend_number) == 0) { | 341 | if (m_friend_exists(av->m, friend_number) == 0) { |
@@ -308,9 +350,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
308 | goto END; | 350 | goto END; |
309 | } | 351 | } |
310 | 352 | ||
311 | /* TODO rest of these */ | 353 | switch (control) { |
312 | switch (control) | ||
313 | { | ||
314 | case TOXAV_CALL_CONTROL_RESUME: { | 354 | case TOXAV_CALL_CONTROL_RESUME: { |
315 | if (!call->active) { | 355 | if (!call->active) { |
316 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | 356 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; |
@@ -319,10 +359,10 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
319 | 359 | ||
320 | /* Only act if paused and had media transfer active before */ | 360 | /* Only act if paused and had media transfer active before */ |
321 | if (call->msi_call->self_capabilities == 0 && | 361 | if (call->msi_call->self_capabilities == 0 && |
322 | call->last_capabilities ) { | 362 | call->last_self_capabilities ) { |
323 | 363 | ||
324 | if (msi_change_capabilities(call->msi_call, | 364 | if (msi_change_capabilities(call->msi_call, |
325 | call->last_capabilities) == -1) { | 365 | call->last_self_capabilities) == -1) { |
326 | /* The only reason for this function to fail is invalid state | 366 | /* The only reason for this function to fail is invalid state |
327 | * ( not active ) */ | 367 | * ( not active ) */ |
328 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | 368 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; |
@@ -342,7 +382,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
342 | 382 | ||
343 | /* Only act if not already paused */ | 383 | /* Only act if not already paused */ |
344 | if (call->msi_call->self_capabilities) { | 384 | if (call->msi_call->self_capabilities) { |
345 | call->last_capabilities = call->msi_call->self_capabilities; | 385 | call->last_self_capabilities = call->msi_call->self_capabilities; |
346 | 386 | ||
347 | if (msi_change_capabilities(call->msi_call, 0) == -1 ) { | 387 | if (msi_change_capabilities(call->msi_call, 0) == -1 ) { |
348 | /* The only reason for this function to fail is invalid state | 388 | /* The only reason for this function to fail is invalid state |
@@ -365,7 +405,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
365 | call_remove(call); | 405 | call_remove(call); |
366 | } break; | 406 | } break; |
367 | 407 | ||
368 | case TOXAV_CALL_CONTROL_MUTE_AUDIO: { | 408 | case TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO: { |
369 | if (!call->active) { | 409 | if (!call->active) { |
370 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | 410 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; |
371 | goto END; | 411 | goto END; |
@@ -381,54 +421,42 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
381 | } | 421 | } |
382 | 422 | ||
383 | rtp_stop_receiving(call->rtps[audio_index]); | 423 | rtp_stop_receiving(call->rtps[audio_index]); |
384 | } | 424 | } else { |
385 | } break; | 425 | /* This call was already muted so notify the friend that he can |
386 | 426 | * start sending audio again | |
387 | case TOXAV_CALL_CONTROL_MUTE_VIDEO: { | 427 | */ |
388 | if (!call->active) { | ||
389 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
390 | goto END; | ||
391 | } | ||
392 | |||
393 | if (call->msi_call->self_capabilities & msi_CapRVideo) { | ||
394 | if (msi_change_capabilities(call->msi_call, call-> | 428 | if (msi_change_capabilities(call->msi_call, call-> |
395 | msi_call->self_capabilities ^ msi_CapRVideo) == -1) { | 429 | msi_call->self_capabilities | msi_CapRAudio) == -1) { |
396 | /* The only reason for this function to fail is invalid state | 430 | /* The only reason for this function to fail is invalid state |
397 | * ( not active ) */ | 431 | * ( not active ) */ |
398 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | 432 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; |
399 | goto END; | 433 | goto END; |
400 | } | 434 | } |
401 | 435 | ||
402 | rtp_stop_receiving(call->rtps[video_index]); | 436 | rtp_start_receiving(call->rtps[audio_index]); |
403 | } | 437 | } |
404 | } break; | 438 | } break; |
405 | 439 | ||
406 | case TOXAV_CALL_CONTROL_UNMUTE_AUDIO: { | 440 | case TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO: { |
407 | if (!call->active) { | 441 | if (!call->active) { |
408 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | 442 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; |
409 | goto END; | 443 | goto END; |
410 | } | 444 | } |
411 | 445 | ||
412 | if (call->msi_call->self_capabilities & ~msi_CapRAudio) { | 446 | if (call->msi_call->self_capabilities & msi_CapRVideo) { |
413 | if (msi_change_capabilities(call->msi_call, call-> | 447 | if (msi_change_capabilities(call->msi_call, call-> |
414 | msi_call->self_capabilities | msi_CapRAudio) == -1) { | 448 | msi_call->self_capabilities ^ msi_CapRVideo) == -1) { |
415 | /* The only reason for this function to fail is invalid state | 449 | /* The only reason for this function to fail is invalid state |
416 | * ( not active ) */ | 450 | * ( not active ) */ |
417 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | 451 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; |
418 | goto END; | 452 | goto END; |
419 | } | 453 | } |
420 | 454 | ||
421 | rtp_start_receiving(call->rtps[audio_index]); | 455 | rtp_stop_receiving(call->rtps[video_index]); |
422 | } | 456 | } else { |
423 | } break; | 457 | /* This call was already muted so notify the friend that he can |
424 | 458 | * start sending video again | |
425 | case TOXAV_CALL_CONTROL_UNMUTE_VIDEO: { | 459 | */ |
426 | if (!call->active) { | ||
427 | rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; | ||
428 | goto END; | ||
429 | } | ||
430 | |||
431 | if (call->msi_call->self_capabilities & ~msi_CapRVideo) { | ||
432 | if (msi_change_capabilities(call->msi_call, call-> | 460 | if (msi_change_capabilities(call->msi_call, call-> |
433 | msi_call->self_capabilities | msi_CapRVideo) == -1) { | 461 | msi_call->self_capabilities | msi_CapRVideo) == -1) { |
434 | /* The only reason for this function to fail is invalid state | 462 | /* The only reason for this function to fail is invalid state |
@@ -443,6 +471,8 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co | |||
443 | } | 471 | } |
444 | 472 | ||
445 | END: | 473 | END: |
474 | pthread_mutex_unlock(av->mutex); | ||
475 | |||
446 | if (error) | 476 | if (error) |
447 | *error = rc; | 477 | *error = rc; |
448 | 478 | ||
@@ -461,7 +491,10 @@ bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_ | |||
461 | 491 | ||
462 | void toxav_callback_request_video_frame(ToxAV* av, toxav_request_video_frame_cb* function, void* user_data) | 492 | void toxav_callback_request_video_frame(ToxAV* av, toxav_request_video_frame_cb* function, void* user_data) |
463 | { | 493 | { |
464 | /* TODO */ | 494 | pthread_mutex_lock(av->mutex); |
495 | av->rvcb.first = function; | ||
496 | av->rvcb.second = user_data; | ||
497 | pthread_mutex_unlock(av->mutex); | ||
465 | } | 498 | } |
466 | 499 | ||
467 | bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, TOXAV_ERR_SEND_FRAME* error) | 500 | bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, TOXAV_ERR_SEND_FRAME* error) |
@@ -474,24 +507,32 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u | |||
474 | goto END; | 507 | goto END; |
475 | } | 508 | } |
476 | 509 | ||
510 | pthread_mutex_lock(av->mutex); | ||
477 | call = call_get(av, friend_number); | 511 | call = call_get(av, friend_number); |
478 | if (call == NULL) { | 512 | if (call == NULL || !call->active) { |
513 | pthread_mutex_unlock(av->mutex); | ||
479 | rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; | 514 | rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; |
480 | goto END; | 515 | goto END; |
481 | } | 516 | } |
482 | 517 | ||
518 | pthread_mutex_lock(call->mutex_video_sending); | ||
519 | pthread_mutex_unlock(av->mutex); | ||
520 | |||
483 | if (call->msi_call->state != msi_CallActive) { | 521 | if (call->msi_call->state != msi_CallActive) { |
484 | /* TODO */ | 522 | /* TODO */ |
523 | pthread_mutex_unlock(call->mutex_video_sending); | ||
485 | rc = TOXAV_ERR_SEND_FRAME_NOT_REQUESTED; | 524 | rc = TOXAV_ERR_SEND_FRAME_NOT_REQUESTED; |
486 | goto END; | 525 | goto END; |
487 | } | 526 | } |
488 | 527 | ||
489 | if ( y == NULL || u == NULL || v == NULL ) { | 528 | if ( y == NULL || u == NULL || v == NULL ) { |
529 | pthread_mutex_unlock(call->mutex_video_sending); | ||
490 | rc = TOXAV_ERR_SEND_FRAME_NULL; | 530 | rc = TOXAV_ERR_SEND_FRAME_NULL; |
491 | goto END; | 531 | goto END; |
492 | } | 532 | } |
493 | 533 | ||
494 | if ( cs_set_sending_video_resolution(call->cs, width, height) != 0 ) { | 534 | if ( cs_set_sending_video_resolution(call->cs, width, height) != 0 ) { |
535 | pthread_mutex_unlock(call->mutex_video_sending); | ||
495 | rc = TOXAV_ERR_SEND_FRAME_INVALID; | 536 | rc = TOXAV_ERR_SEND_FRAME_INVALID; |
496 | goto END; | 537 | goto END; |
497 | } | 538 | } |
@@ -513,6 +554,7 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u | |||
513 | 554 | ||
514 | vpx_img_free(&img); /* FIXME don't free? */ | 555 | vpx_img_free(&img); /* FIXME don't free? */ |
515 | if ( vrc != VPX_CODEC_OK) { | 556 | if ( vrc != VPX_CODEC_OK) { |
557 | pthread_mutex_unlock(call->mutex_video_sending); | ||
516 | LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(vrc)); | 558 | LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(vrc)); |
517 | rc = TOXAV_ERR_SEND_FRAME_INVALID; | 559 | rc = TOXAV_ERR_SEND_FRAME_INVALID; |
518 | goto END; | 560 | goto END; |
@@ -542,13 +584,18 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u | |||
542 | for (i = 0; i < parts; i++) { | 584 | for (i = 0; i < parts; i++) { |
543 | iter = cs_iterate_split_video_frame(call->cs, &part_size); | 585 | iter = cs_iterate_split_video_frame(call->cs, &part_size); |
544 | 586 | ||
545 | if (rtp_send_msg(call->rtps[video_index], iter, part_size) < 0) | 587 | if (rtp_send_msg(call->rtps[video_index], iter, part_size) < 0) { |
588 | pthread_mutex_unlock(call->mutex_video_sending); | ||
589 | LOGGER_WARNING("Could not send video frame: %s\n", strerror(errno)); | ||
546 | goto END; | 590 | goto END; |
591 | } | ||
547 | } | 592 | } |
548 | } | 593 | } |
549 | } | 594 | } |
550 | } | 595 | } |
551 | 596 | ||
597 | pthread_mutex_unlock(call->mutex_video_sending); | ||
598 | |||
552 | END: | 599 | END: |
553 | if (error) | 600 | if (error) |
554 | *error = rc; | 601 | *error = rc; |
@@ -558,7 +605,10 @@ END: | |||
558 | 605 | ||
559 | void toxav_callback_request_audio_frame(ToxAV* av, toxav_request_audio_frame_cb* function, void* user_data) | 606 | void toxav_callback_request_audio_frame(ToxAV* av, toxav_request_audio_frame_cb* function, void* user_data) |
560 | { | 607 | { |
561 | /* TODO */ | 608 | pthread_mutex_lock(av->mutex); |
609 | av->racb.first = function; | ||
610 | av->racb.second = user_data; | ||
611 | pthread_mutex_unlock(av->mutex); | ||
562 | } | 612 | } |
563 | 613 | ||
564 | bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME* error) | 614 | bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME* error) |
@@ -571,24 +621,32 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc | |||
571 | goto END; | 621 | goto END; |
572 | } | 622 | } |
573 | 623 | ||
624 | pthread_mutex_lock(av->mutex); | ||
574 | call = call_get(av, friend_number); | 625 | call = call_get(av, friend_number); |
575 | if (call == NULL) { | 626 | if (call == NULL || !call->active) { |
627 | pthread_mutex_unlock(av->mutex); | ||
576 | rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; | 628 | rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; |
577 | goto END; | 629 | goto END; |
578 | } | 630 | } |
579 | 631 | ||
632 | pthread_mutex_lock(call->mutex_audio_sending); | ||
633 | pthread_mutex_unlock(av->mutex); | ||
634 | |||
580 | if (call->msi_call->state != msi_CallActive) { | 635 | if (call->msi_call->state != msi_CallActive) { |
581 | /* TODO */ | 636 | /* TODO */ |
637 | pthread_mutex_unlock(call->mutex_audio_sending); | ||
582 | rc = TOXAV_ERR_SEND_FRAME_NOT_REQUESTED; | 638 | rc = TOXAV_ERR_SEND_FRAME_NOT_REQUESTED; |
583 | goto END; | 639 | goto END; |
584 | } | 640 | } |
585 | 641 | ||
586 | if ( pcm == NULL ) { | 642 | if ( pcm == NULL ) { |
643 | pthread_mutex_unlock(call->mutex_audio_sending); | ||
587 | rc = TOXAV_ERR_SEND_FRAME_NULL; | 644 | rc = TOXAV_ERR_SEND_FRAME_NULL; |
588 | goto END; | 645 | goto END; |
589 | } | 646 | } |
590 | 647 | ||
591 | if ( channels != 1 || channels != 2 ) { | 648 | if ( channels != 1 || channels != 2 ) { |
649 | pthread_mutex_unlock(call->mutex_audio_sending); | ||
592 | rc = TOXAV_ERR_SEND_FRAME_INVALID; | 650 | rc = TOXAV_ERR_SEND_FRAME_INVALID; |
593 | goto END; | 651 | goto END; |
594 | } | 652 | } |
@@ -604,6 +662,7 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc | |||
604 | if (vrc < 0) { | 662 | if (vrc < 0) { |
605 | LOGGER_WARNING("Failed to encode frame"); | 663 | LOGGER_WARNING("Failed to encode frame"); |
606 | rc = TOXAV_ERR_SEND_FRAME_INVALID; | 664 | rc = TOXAV_ERR_SEND_FRAME_INVALID; |
665 | pthread_mutex_unlock(call->mutex_audio_sending); | ||
607 | goto END; | 666 | goto END; |
608 | } | 667 | } |
609 | 668 | ||
@@ -611,6 +670,8 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc | |||
611 | /* TODO check for error? */ | 670 | /* TODO check for error? */ |
612 | } | 671 | } |
613 | 672 | ||
673 | pthread_mutex_unlock(call->mutex_audio_sending); | ||
674 | |||
614 | END: | 675 | END: |
615 | if (error) | 676 | if (error) |
616 | *error = rc; | 677 | *error = rc; |
@@ -620,14 +681,18 @@ END: | |||
620 | 681 | ||
621 | void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data) | 682 | void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data) |
622 | { | 683 | { |
684 | pthread_mutex_lock(av->mutex); | ||
623 | av->vcb.first = function; | 685 | av->vcb.first = function; |
624 | av->vcb.second = user_data; | 686 | av->vcb.second = user_data; |
687 | pthread_mutex_unlock(av->mutex); | ||
625 | } | 688 | } |
626 | 689 | ||
627 | void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* function, void* user_data) | 690 | void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* function, void* user_data) |
628 | { | 691 | { |
692 | pthread_mutex_lock(av->mutex); | ||
629 | av->acb.first = function; | 693 | av->acb.first = function; |
630 | av->acb.second = user_data; | 694 | av->acb.second = user_data; |
695 | pthread_mutex_unlock(av->mutex); | ||
631 | } | 696 | } |
632 | 697 | ||
633 | 698 | ||
@@ -639,10 +704,12 @@ void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* | |||
639 | int callback_invite(void* toxav_inst, MSICall* call) | 704 | int callback_invite(void* toxav_inst, MSICall* call) |
640 | { | 705 | { |
641 | ToxAV* toxav = toxav_inst; | 706 | ToxAV* toxav = toxav_inst; |
707 | pthread_mutex_lock(toxav->mutex); | ||
642 | 708 | ||
643 | ToxAVCall* av_call = call_new(toxav, call->friend_id, NULL); | 709 | ToxAVCall* av_call = call_new(toxav, call->friend_id, NULL); |
644 | if (av_call == NULL) { | 710 | if (av_call == NULL) { |
645 | LOGGER_WARNING("Failed to initialize call..."); | 711 | LOGGER_WARNING("Failed to initialize call..."); |
712 | pthread_mutex_unlock(toxav->mutex); | ||
646 | return -1; | 713 | return -1; |
647 | } | 714 | } |
648 | 715 | ||
@@ -653,36 +720,41 @@ int callback_invite(void* toxav_inst, MSICall* call) | |||
653 | toxav->ccb.first(toxav, call->friend_id, call->peer_capabilities & msi_CapSAudio, | 720 | toxav->ccb.first(toxav, call->friend_id, call->peer_capabilities & msi_CapSAudio, |
654 | call->peer_capabilities & msi_CapSVideo, toxav->ccb.second); | 721 | call->peer_capabilities & msi_CapSVideo, toxav->ccb.second); |
655 | 722 | ||
723 | pthread_mutex_unlock(toxav->mutex); | ||
656 | return 0; | 724 | return 0; |
657 | } | 725 | } |
658 | 726 | ||
659 | int callback_start(void* toxav_inst, MSICall* call) | 727 | int callback_start(void* toxav_inst, MSICall* call) |
660 | { | 728 | { |
661 | ToxAV* toxav = toxav_inst; | 729 | ToxAV* toxav = toxav_inst; |
730 | pthread_mutex_lock(toxav->mutex); | ||
662 | 731 | ||
663 | ToxAVCall* av_call = call_get(toxav, call->friend_id); | 732 | ToxAVCall* av_call = call_get(toxav, call->friend_id); |
664 | 733 | ||
665 | if (av_call == NULL) { | 734 | if (av_call == NULL) { |
666 | /* Should this ever happen? */ | 735 | /* Should this ever happen? */ |
736 | pthread_mutex_unlock(toxav->mutex); | ||
667 | return -1; | 737 | return -1; |
668 | } | 738 | } |
669 | 739 | ||
670 | if (!call_prepare_transmission(av_call)) { | 740 | if (!call_prepare_transmission(av_call)) { |
671 | callback_error(toxav_inst, call); | 741 | callback_error(toxav_inst, call); |
672 | call_remove(av_call); | 742 | call_remove(av_call); |
743 | pthread_mutex_unlock(toxav->mutex); | ||
673 | return -1; | 744 | return -1; |
674 | } | 745 | } |
675 | 746 | ||
676 | if (toxav->scb.first) | 747 | if (toxav->scb.first) |
677 | toxav->scb.first(toxav, call->friend_id, | 748 | toxav->scb.first(toxav, call->friend_id, call->peer_capabilities, toxav->scb.second); |
678 | capabilities_to_state(call->peer_capabilities), toxav->scb.second); | ||
679 | 749 | ||
750 | pthread_mutex_unlock(toxav->mutex); | ||
680 | return 0; | 751 | return 0; |
681 | } | 752 | } |
682 | 753 | ||
683 | int callback_end(void* toxav_inst, MSICall* call) | 754 | int callback_end(void* toxav_inst, MSICall* call) |
684 | { | 755 | { |
685 | ToxAV* toxav = toxav_inst; | 756 | ToxAV* toxav = toxav_inst; |
757 | pthread_mutex_lock(toxav->mutex); | ||
686 | 758 | ||
687 | if (toxav->scb.first) | 759 | if (toxav->scb.first) |
688 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second); | 760 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second); |
@@ -690,43 +762,39 @@ int callback_end(void* toxav_inst, MSICall* call) | |||
690 | call_kill_transmission(call->av_call); | 762 | call_kill_transmission(call->av_call); |
691 | call_remove(call->av_call); | 763 | call_remove(call->av_call); |
692 | 764 | ||
765 | pthread_mutex_unlock(toxav->mutex); | ||
693 | return 0; | 766 | return 0; |
694 | } | 767 | } |
695 | 768 | ||
696 | int callback_error(void* toxav_inst, MSICall* call) | 769 | int callback_error(void* toxav_inst, MSICall* call) |
697 | { | 770 | { |
698 | ToxAV* toxav = toxav_inst; | 771 | ToxAV* toxav = toxav_inst; |
772 | pthread_mutex_lock(toxav->mutex); | ||
699 | 773 | ||
700 | if (toxav->scb.first) | 774 | if (toxav->scb.first) |
701 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second); | 775 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second); |
702 | 776 | ||
777 | call_kill_transmission(call->av_call); | ||
778 | call_remove(call->av_call); | ||
779 | |||
780 | pthread_mutex_unlock(toxav->mutex); | ||
703 | return 0; | 781 | return 0; |
704 | } | 782 | } |
705 | 783 | ||
706 | int callback_capabilites(void* toxav_inst, MSICall* call) | 784 | int callback_capabilites(void* toxav_inst, MSICall* call) |
707 | { | 785 | { |
708 | ToxAV* toxav = toxav_inst; | 786 | ToxAV* toxav = toxav_inst; |
787 | pthread_mutex_lock(toxav->mutex); | ||
788 | |||
789 | /* TODO modify cs? */ | ||
790 | |||
709 | if (toxav->scb.first) | 791 | if (toxav->scb.first) |
710 | toxav->scb.first(toxav, call->friend_id, | 792 | toxav->scb.first(toxav, call->friend_id, call->peer_capabilities, toxav->scb.second); |
711 | capabilities_to_state(call->peer_capabilities), toxav->scb.second); | ||
712 | 793 | ||
794 | pthread_mutex_unlock(toxav->mutex); | ||
713 | return 0; | 795 | return 0; |
714 | } | 796 | } |
715 | 797 | ||
716 | TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities) | ||
717 | { | ||
718 | if (capabilities == 0) | ||
719 | return TOXAV_CALL_STATE_PAUSED; | ||
720 | else if ((capabilities & msi_CapSAudio) && (capabilities & msi_CapSVideo)) | ||
721 | return TOXAV_CALL_STATE_SENDING_AV; | ||
722 | else if (capabilities & msi_CapSAudio) | ||
723 | return TOXAV_CALL_STATE_SENDING_A; | ||
724 | else if (capabilities & msi_CapSVideo) | ||
725 | return TOXAV_CALL_STATE_SENDING_V; | ||
726 | |||
727 | return TOXAV_CALL_STATE_NOT_SENDING; | ||
728 | } | ||
729 | |||
730 | bool audio_bitrate_invalid(uint32_t bitrate) | 798 | bool audio_bitrate_invalid(uint32_t bitrate) |
731 | { | 799 | { |
732 | /* Opus RFC 6716 section-2.1.1 dictates the following: | 800 | /* Opus RFC 6716 section-2.1.1 dictates the following: |
@@ -743,6 +811,7 @@ bool video_bitrate_invalid(uint32_t bitrate) | |||
743 | 811 | ||
744 | ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error) | 812 | ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error) |
745 | { | 813 | { |
814 | /* Assumes mutex locked */ | ||
746 | TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK; | 815 | TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK; |
747 | ToxAVCall* call = NULL; | 816 | ToxAVCall* call = NULL; |
748 | 817 | ||
@@ -772,28 +841,10 @@ ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error) | |||
772 | call->av = av; | 841 | call->av = av; |
773 | call->friend_id = friend_number; | 842 | call->friend_id = friend_number; |
774 | 843 | ||
775 | if (create_recursive_mutex(call->mutex_control) != 0) { | ||
776 | free(call); | ||
777 | call = NULL; | ||
778 | rc = TOXAV_ERR_CALL_MALLOC; | ||
779 | goto END; | ||
780 | } | ||
781 | |||
782 | if (create_recursive_mutex(call->mutex_do) != 0) { | ||
783 | pthread_mutex_destroy(call->mutex_control); | ||
784 | free(call); | ||
785 | call = NULL; | ||
786 | rc = TOXAV_ERR_CALL_MALLOC; | ||
787 | goto END; | ||
788 | } | ||
789 | |||
790 | |||
791 | if (av->calls == NULL) { /* Creating */ | 844 | if (av->calls == NULL) { /* Creating */ |
792 | av->calls = calloc (sizeof(ToxAVCall*), friend_number + 1); | 845 | av->calls = calloc (sizeof(ToxAVCall*), friend_number + 1); |
793 | 846 | ||
794 | if (av->calls == NULL) { | 847 | if (av->calls == NULL) { |
795 | pthread_mutex_destroy(call->mutex_control); | ||
796 | pthread_mutex_destroy(call->mutex_do); | ||
797 | free(call); | 848 | free(call); |
798 | call = NULL; | 849 | call = NULL; |
799 | rc = TOXAV_ERR_CALL_MALLOC; | 850 | rc = TOXAV_ERR_CALL_MALLOC; |
@@ -806,8 +857,6 @@ ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error) | |||
806 | void* tmp = realloc(av->calls, sizeof(ToxAVCall*) * friend_number + 1); | 857 | void* tmp = realloc(av->calls, sizeof(ToxAVCall*) * friend_number + 1); |
807 | 858 | ||
808 | if (tmp == NULL) { | 859 | if (tmp == NULL) { |
809 | pthread_mutex_destroy(call->mutex_control); | ||
810 | pthread_mutex_destroy(call->mutex_do); | ||
811 | free(call); | 860 | free(call); |
812 | call = NULL; | 861 | call = NULL; |
813 | rc = TOXAV_ERR_CALL_MALLOC; | 862 | rc = TOXAV_ERR_CALL_MALLOC; |
@@ -843,6 +892,7 @@ END: | |||
843 | 892 | ||
844 | ToxAVCall* call_get(ToxAV* av, uint32_t friend_number) | 893 | ToxAVCall* call_get(ToxAV* av, uint32_t friend_number) |
845 | { | 894 | { |
895 | /* Assumes mutex locked */ | ||
846 | if (av->calls == NULL || av->calls_tail < friend_number) | 896 | if (av->calls == NULL || av->calls_tail < friend_number) |
847 | return NULL; | 897 | return NULL; |
848 | 898 | ||
@@ -851,6 +901,8 @@ ToxAVCall* call_get(ToxAV* av, uint32_t friend_number) | |||
851 | 901 | ||
852 | bool call_prepare_transmission(ToxAVCall* call) | 902 | bool call_prepare_transmission(ToxAVCall* call) |
853 | { | 903 | { |
904 | /* Assumes mutex locked */ | ||
905 | |||
854 | if (call == NULL) | 906 | if (call == NULL) |
855 | return false; | 907 | return false; |
856 | 908 | ||
@@ -860,25 +912,22 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
860 | /* It makes no sense to have CSession without callbacks */ | 912 | /* It makes no sense to have CSession without callbacks */ |
861 | return false; | 913 | return false; |
862 | 914 | ||
863 | pthread_mutex_lock(call->mutex_control); | ||
864 | |||
865 | if (call->active) { | 915 | if (call->active) { |
866 | pthread_mutex_unlock(call->mutex_control); | ||
867 | LOGGER_WARNING("Call already active!\n"); | 916 | LOGGER_WARNING("Call already active!\n"); |
868 | return true; | 917 | return true; |
869 | } | 918 | } |
870 | 919 | ||
871 | if (pthread_mutex_init(call->mutex_encoding_audio, NULL) != 0) | 920 | if (pthread_mutex_init(call->mutex_audio_sending, NULL) != 0) |
872 | goto MUTEX_INIT_ERROR; | 921 | goto MUTEX_INIT_ERROR; |
873 | 922 | ||
874 | if (pthread_mutex_init(call->mutex_encoding_video, NULL) != 0) { | 923 | if (pthread_mutex_init(call->mutex_video_sending, NULL) != 0) { |
875 | pthread_mutex_destroy(call->mutex_encoding_audio); | 924 | pthread_mutex_destroy(call->mutex_audio_sending); |
876 | goto MUTEX_INIT_ERROR; | 925 | goto MUTEX_INIT_ERROR; |
877 | } | 926 | } |
878 | 927 | ||
879 | if (pthread_mutex_init(call->mutex_do, NULL) != 0) { | 928 | if (pthread_mutex_init(call->mutex_decoding, NULL) != 0) { |
880 | pthread_mutex_destroy(call->mutex_encoding_audio); | 929 | pthread_mutex_destroy(call->mutex_audio_sending); |
881 | pthread_mutex_destroy(call->mutex_encoding_video); | 930 | pthread_mutex_destroy(call->mutex_video_sending); |
882 | goto MUTEX_INIT_ERROR; | 931 | goto MUTEX_INIT_ERROR; |
883 | } | 932 | } |
884 | 933 | ||
@@ -945,7 +994,6 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
945 | } | 994 | } |
946 | 995 | ||
947 | call->active = 1; | 996 | call->active = 1; |
948 | pthread_mutex_unlock(call->mutex_control); | ||
949 | return true; | 997 | return true; |
950 | 998 | ||
951 | FAILURE: | 999 | FAILURE: |
@@ -955,16 +1003,12 @@ FAILURE: | |||
955 | call->rtps[video_index] = NULL; | 1003 | call->rtps[video_index] = NULL; |
956 | cs_kill(call->cs); | 1004 | cs_kill(call->cs); |
957 | call->cs = NULL; | 1005 | call->cs = NULL; |
958 | call->active = 0; | 1006 | pthread_mutex_destroy(call->mutex_audio_sending); |
959 | pthread_mutex_destroy(call->mutex_encoding_audio); | 1007 | pthread_mutex_destroy(call->mutex_video_sending); |
960 | pthread_mutex_destroy(call->mutex_encoding_video); | 1008 | pthread_mutex_destroy(call->mutex_decoding); |
961 | pthread_mutex_destroy(call->mutex_do); | ||
962 | |||
963 | pthread_mutex_unlock(call->mutex_control); | ||
964 | return false; | 1009 | return false; |
965 | 1010 | ||
966 | MUTEX_INIT_ERROR: | 1011 | MUTEX_INIT_ERROR: |
967 | pthread_mutex_unlock(call->mutex_control); | ||
968 | LOGGER_ERROR("Mutex initialization failed!\n"); | 1012 | LOGGER_ERROR("Mutex initialization failed!\n"); |
969 | return false; | 1013 | return false; |
970 | } | 1014 | } |
@@ -974,29 +1018,26 @@ void call_kill_transmission(ToxAVCall* call) | |||
974 | if (call == NULL || call->active == 0) | 1018 | if (call == NULL || call->active == 0) |
975 | return; | 1019 | return; |
976 | 1020 | ||
977 | pthread_mutex_lock(call->mutex_control); | ||
978 | |||
979 | call->active = 0; | 1021 | call->active = 0; |
980 | 1022 | ||
981 | pthread_mutex_lock(call->mutex_encoding_audio); | 1023 | pthread_mutex_lock(call->mutex_audio_sending); |
982 | pthread_mutex_unlock(call->mutex_encoding_audio); | 1024 | pthread_mutex_unlock(call->mutex_audio_sending); |
983 | pthread_mutex_lock(call->mutex_encoding_video); | 1025 | pthread_mutex_lock(call->mutex_video_sending); |
984 | pthread_mutex_unlock(call->mutex_encoding_video); | 1026 | pthread_mutex_unlock(call->mutex_video_sending); |
985 | pthread_mutex_lock(call->mutex_do); | 1027 | pthread_mutex_lock(call->mutex_decoding); |
986 | pthread_mutex_unlock(call->mutex_do); | 1028 | pthread_mutex_unlock(call->mutex_decoding); |
987 | 1029 | ||
988 | rtp_kill(call->rtps[audio_index]); | 1030 | rtp_kill(call->rtps[audio_index]); |
989 | call->rtps[audio_index] = NULL; | 1031 | call->rtps[audio_index] = NULL; |
990 | rtp_kill(call->rtps[video_index]); | 1032 | rtp_kill(call->rtps[video_index]); |
991 | call->rtps[video_index] = NULL; | 1033 | call->rtps[video_index] = NULL; |
1034 | |||
992 | cs_kill(call->cs); | 1035 | cs_kill(call->cs); |
993 | call->cs = NULL; | 1036 | call->cs = NULL; |
994 | 1037 | ||
995 | pthread_mutex_destroy(call->mutex_encoding_audio); | 1038 | pthread_mutex_destroy(call->mutex_audio_sending); |
996 | pthread_mutex_destroy(call->mutex_encoding_video); | 1039 | pthread_mutex_destroy(call->mutex_video_sending); |
997 | pthread_mutex_destroy(call->mutex_do); | 1040 | pthread_mutex_destroy(call->mutex_decoding); |
998 | |||
999 | pthread_mutex_unlock(call->mutex_control); | ||
1000 | } | 1041 | } |
1001 | 1042 | ||
1002 | void call_remove(ToxAVCall* call) | 1043 | void call_remove(ToxAVCall* call) |
@@ -1010,9 +1051,6 @@ void call_remove(ToxAVCall* call) | |||
1010 | ToxAVCall* prev = call->prev; | 1051 | ToxAVCall* prev = call->prev; |
1011 | ToxAVCall* next = call->next; | 1052 | ToxAVCall* next = call->next; |
1012 | 1053 | ||
1013 | pthread_mutex_destroy(call->mutex_control); | ||
1014 | pthread_mutex_destroy(call->mutex_do); | ||
1015 | |||
1016 | free(call); | 1054 | free(call); |
1017 | 1055 | ||
1018 | if (prev) | 1056 | if (prev) |