summaryrefslogtreecommitdiff
path: root/toxav/toxav_new.c
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-01-24 23:29:54 +0100
committermannol <eniz_vukovic@hotmail.com>2015-01-24 23:29:54 +0100
commit1450c22d01cbb5185ee8eac14657ddf3301d7e48 (patch)
tree366f795f56689b0fb53dfe52941fb9c813429e8b /toxav/toxav_new.c
parente57fb8c12ea7de1a5070ea0fc6f14c8e242c409f (diff)
Current progress
Diffstat (limited to 'toxav/toxav_new.c')
-rw-r--r--toxav/toxav_new.c710
1 files changed, 710 insertions, 0 deletions
diff --git a/toxav/toxav_new.c b/toxav/toxav_new.c
new file mode 100644
index 00000000..d6c1872c
--- /dev/null
+++ b/toxav/toxav_new.c
@@ -0,0 +1,710 @@
1/** toxav.c
2 *
3 * Copyright (C) 2013 Tox project All Rights Reserved.
4 *
5 * This file is part of Tox.
6 *
7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif /* HAVE_CONFIG_H */
25
26#include "toxav_new.h"
27#include "msi.h" /* Includes codec.h and rtp.h */
28
29#include "../toxcore/Messenger.h"
30#include "../toxcore/logger.h"
31#include "../toxcore/util.h"
32
33#include <assert.h>
34#include <stdlib.h>
35#include <string.h>
36
37
38enum {
39 audio_index,
40 video_index,
41};
42
43typedef struct iToxAVCall
44{
45 pthread_mutex_t mutex_control[1];
46 pthread_mutex_t mutex_encoding_audio[1];
47 pthread_mutex_t mutex_encoding_video[1];
48 pthread_mutex_t mutex_do[1];
49 RTPSession *rtps[2]; /** Audio is first and video is second */
50 CSSession *cs;
51 bool active;
52 int32_t friend_number;
53 int32_t call_idx; /* FIXME msi compat, remove */
54
55 struct iToxAVCall *prev;
56 struct iToxAVCall *next;
57} IToxAVCall;
58
59struct toxAV
60{
61 Messenger* m;
62 MSISession* msi;
63
64 /* Two-way storage: first is array of calls and second is list of calls with head and tail */
65 IToxAVCall** calls;
66 uint32_t calls_tail;
67 uint32_t calls_head;
68
69 PAIR(toxav_call_cb *, void*) ccb; /* Call callback */
70 PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */
71 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */
72 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */
73
74 /** Decode time measures */
75 int32_t dmssc; /** Measure count */
76 int32_t dmsst; /** Last cycle total */
77 int32_t dmssa; /** Average decoding time in ms */
78};
79
80
81void i_toxav_msi_callback_invite(void* toxav_inst, int32_t call_idx, void *data);
82void i_toxav_msi_callback_ringing(void* toxav_inst, int32_t call_idx, void *data);
83void i_toxav_msi_callback_start(void* toxav_inst, int32_t call_idx, void *data);
84void i_toxav_msi_callback_cancel(void* toxav_inst, int32_t call_idx, void *data);
85void i_toxav_msi_callback_reject(void* toxav_inst, int32_t call_idx, void *data);
86void i_toxav_msi_callback_end(void* toxav_inst, int32_t call_idx, void *data);
87void i_toxav_msi_callback_request_to(void* toxav_inst, int32_t call_idx, void *data); /* TODO remove */
88void i_toxav_msi_callback_peer_to(void* toxav_inst, int32_t call_idx, void *data);
89void i_toxav_msi_callback_state_change(void* toxav_inst, int32_t call_idx, void *data);
90
91IToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number);
92IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number);
93void i_toxav_remove_call(ToxAV* av, uint32_t friend_number);
94bool i_toxav_audio_bitrate_invalid(uint32_t bitrate);
95bool i_toxav_video_bitrate_invalid(uint32_t bitrate);
96IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error);
97bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call);
98void i_toxav_kill_transmission(ToxAV* av, IToxAVCall* call);
99
100
101
102ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
103{
104 TOXAV_ERR_NEW rc = TOXAV_ERR_NEW_OK;
105 ToxAV *av = NULL;
106
107 if (tox == NULL) {
108 rc = TOXAV_ERR_NEW_NULL;
109 goto FAILURE;
110 }
111
112 if (((Messenger*)tox)->msi_packet) {
113 rc = TOXAV_ERR_NEW_MULTIPLE;
114 goto FAILURE;
115 }
116
117 av = calloc ( sizeof(ToxAV), 1);
118
119 if (av == NULL) {
120 LOGGER_WARNING("Allocation failed!");
121 rc = TOXAV_ERR_NEW_MALLOC;
122 goto FAILURE;
123 }
124
125 av->m = (Messenger *)tox;
126 av->msi = msi_new(av->m, 100); /* TODO remove max calls */
127
128 if (av->msi == NULL) {
129 rc = TOXAV_ERR_NEW_MALLOC;
130 goto FAILURE;
131 }
132
133 av->msi->agent_handler = av;
134
135 msi_register_callback(av->msi, i_toxav_msi_callback_invite, msi_OnInvite, NULL);
136 msi_register_callback(av->msi, i_toxav_msi_callback_ringing, msi_OnRinging, NULL);
137 msi_register_callback(av->msi, i_toxav_msi_callback_start, msi_OnStart, NULL);
138 msi_register_callback(av->msi, i_toxav_msi_callback_cancel, msi_OnCancel, NULL);
139 msi_register_callback(av->msi, i_toxav_msi_callback_reject, msi_OnReject, NULL);
140 msi_register_callback(av->msi, i_toxav_msi_callback_end, msi_OnEnd, NULL);
141 msi_register_callback(av->msi, i_toxav_msi_callback_request_to, msi_OnRequestTimeout, NULL);
142 msi_register_callback(av->msi, i_toxav_msi_callback_peer_to, msi_OnPeerTimeout, NULL);
143 msi_register_callback(av->msi, i_toxav_msi_callback_state_change, msi_OnPeerCSChange, NULL);
144 msi_register_callback(av->msi, i_toxav_msi_callback_state_change, msi_OnSelfCSChange, NULL);
145
146
147 if (error)
148 *error = rc;
149
150 return av;
151
152FAILURE:
153 if (error)
154 *error = rc;
155
156 free(av);
157
158 return NULL;
159}
160
161void toxav_kill(ToxAV* av)
162{
163 if (av == NULL)
164 return;
165
166 msi_kill(av->msi);
167 /* TODO iterate over calls */
168 free(av);
169}
170
171Tox* toxav_get_tox(ToxAV* av)
172{
173 return (Tox*) av->m;
174}
175
176uint32_t toxav_iteration_interval(const ToxAV* av)
177{
178
179}
180
181void toxav_iteration(ToxAV* av)
182{
183
184}
185
186bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error)
187{
188 IToxAVCall* call = i_toxav_init_call(av, friend_number, audio_bit_rate, video_bit_rate, error);
189 if (call == NULL) {
190 return false;
191 }
192
193 /* TODO remove csettings */
194 MSICSettings csets;
195 csets.audio_bitrate = audio_bit_rate;
196 csets.video_bitrate = video_bit_rate;
197
198 csets.call_type = video_bit_rate ? msi_TypeVideo : msi_TypeAudio;
199
200 if (msi_invite(av->msi, &call->call_idx, &csets, 1000, friend_number) != 0) {
201 i_toxav_remove_call(av, friend_number);
202 if (error)
203 *error = TOXAV_ERR_CALL_MALLOC; /* FIXME: this should be the only reason to fail */
204 return false;
205 }
206
207 return true;
208}
209
210void toxav_callback_call(ToxAV* av, toxav_call_cb* function, void* user_data)
211{
212 av->ccb.first = function;
213 av->ccb.second = user_data;
214}
215
216bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER* error)
217{
218 TOXAV_ERR_ANSWER rc = TOXAV_ERR_ANSWER_OK;
219 if (m_friend_exists(av->m, friend_number)) {
220 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND;
221 goto END;
222 }
223
224 if ((audio_bit_rate && i_toxav_audio_bitrate_invalid(audio_bit_rate))
225 ||(video_bit_rate && i_toxav_video_bitrate_invalid(video_bit_rate))
226 ) {
227 rc = TOXAV_ERR_CALL_INVALID_BIT_RATE;
228 goto END;
229 }
230
231 IToxAVCall* call = i_toxav_get_call(av, friend_number);
232 if (call == NULL || av->msi->calls[call->call_idx]->state != msi_CallRequested) {
233 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING;
234 goto END;
235 }
236
237 /* TODO remove csettings */
238 MSICSettings csets;
239 csets.audio_bitrate = audio_bit_rate;
240 csets.video_bitrate = video_bit_rate;
241
242 csets.call_type = video_bit_rate ? msi_TypeVideo : msi_TypeAudio;
243
244 if (msi_answer(av->msi, call->call_idx, &csets) != 0) {
245 rc = TOXAV_ERR_ANSWER_MALLOC; /* TODO Some error here */
246 /* TODO Reject call? */
247 }
248
249END:
250 if (error)
251 *error = rc;
252
253 return rc == TOXAV_ERR_ANSWER_OK;
254}
255
256void toxav_callback_call_state(ToxAV* av, toxav_call_state_cb* function, void* user_data)
257{
258 av->scb.first = function;
259 av->scb.second = user_data;
260}
261
262bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL* error)
263{
264
265}
266
267bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, TOXAV_ERR_BIT_RATE* error)
268{
269
270}
271
272bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_bit_rate, TOXAV_ERR_BIT_RATE* error)
273{
274
275}
276
277void toxav_callback_request_video_frame(ToxAV* av, toxav_request_video_frame_cb* function, void* user_data)
278{
279
280}
281
282bool 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, const uint8_t* a, TOXAV_ERR_SEND_FRAME* error)
283{
284
285}
286
287void toxav_callback_request_audio_frame(ToxAV* av, toxav_request_audio_frame_cb* function, void* user_data)
288{
289
290}
291
292bool 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)
293{
294
295}
296
297void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data)
298{
299
300}
301
302void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* function, void* user_data)
303{
304
305}
306
307
308/*******************************************************************************
309 *
310 * :: Internal
311 *
312 ******************************************************************************/
313/** TODO:
314 * - In msi call_idx can be the same as friend id
315 * - If crutial callback not present send error
316 * - Remove *data from msi
317 * - Remove CSettings from msi
318 */
319void i_toxav_msi_callback_invite(void* toxav_inst, int32_t call_idx, void* data)
320{
321 ToxAV* toxav = toxav_inst;
322
323 uint32_t ab = toxav->msi->calls[call_idx]->csettings_peer[0].audio_bitrate;
324 uint32_t vb = toxav->msi->calls[call_idx]->csettings_peer[0].video_bitrate;
325
326 IToxAVCall* call = i_toxav_init_call(toxav, toxav->msi->calls[call_idx]->peers[0], ab, vb, NULL);
327 if (call == NULL) {
328 msi_reject(toxav->msi, call_idx, NULL);
329 return false;
330 }
331
332 call->call_idx = call_idx;
333
334 if (toxav->ccb.first)
335 toxav->ccb.first(toxav, toxav->msi->calls[call_idx]->peers[0], true, true, toxav->ccb.second);
336}
337
338void i_toxav_msi_callback_ringing(void* toxav_inst, int32_t call_idx, void* data)
339{
340 ToxAV* toxav = toxav_inst;
341 if (toxav->scb.first)
342 toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
343 TOXAV_CALL_STATE_RINGING, toxav->scb.second);
344}
345
346void i_toxav_msi_callback_start(void* toxav_inst, int32_t call_idx, void* data)
347{
348 ToxAV* toxav = toxav_inst;
349
350 IToxAVCall* call = i_toxav_get_call(toxav, toxav->msi->calls[call_idx]->peers[0]);
351
352 if (call == NULL || !i_toxav_prepare_transmission(toxav, call)) {
353 /* TODO send error */
354 i_toxav_remove_call(toxav, toxav->msi->calls[call_idx]->peers[0]);
355 return;
356 }
357
358 TOXAV_CALL_STATE state;
359 const MSICSettings* csets = toxav->msi->calls[call_idx]->csettings_peer[0];
360
361 if (csets->audio_bitrate && csets->video_bitrate)
362 state = TOXAV_CALL_STATE_SENDING_AV;
363 else if (csets->video_bitrate == 0)
364 state = TOXAV_CALL_STATE_SENDING_A;
365 else
366 state = TOXAV_CALL_STATE_SENDING_V;
367
368 if (toxav->scb.first) /* TODO this */
369 toxav->scb.first(toxav, call->friend_number, state, toxav->scb.second);
370}
371
372void i_toxav_msi_callback_cancel(void* toxav_inst, int32_t call_idx, void* data)
373{
374 ToxAV* toxav = toxav_inst;
375 if (toxav->scb.first)
376 toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
377 TOXAV_CALL_STATE_END, toxav->scb.second);
378}
379
380void i_toxav_msi_callback_reject(void* toxav_inst, int32_t call_idx, void* data)
381{
382 ToxAV* toxav = toxav_inst;
383 if (toxav->scb.first)
384 toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
385 TOXAV_CALL_STATE_END, toxav->scb.second);
386}
387
388void i_toxav_msi_callback_end(void* toxav_inst, int32_t call_idx, void* data)
389{
390 ToxAV* toxav = toxav_inst;
391 if (toxav->scb.first)
392 toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
393 TOXAV_CALL_STATE_END, toxav->scb.second);
394}
395
396void i_toxav_msi_callback_request_to(void* toxav_inst, int32_t call_idx, void* data)
397{
398 /* TODO remove */
399 ToxAV* toxav = toxav_inst;
400 if (toxav->scb.first)
401 toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
402 TOXAV_CALL_STATE_ERROR, toxav->scb.second);
403}
404
405void i_toxav_msi_callback_peer_to(void* toxav_inst, int32_t call_idx, void* data)
406{
407 ToxAV* toxav = toxav_inst;
408 if (toxav->scb.first)
409 toxav->scb.first(toxav, toxav->msi->calls[call_idx]->peers[0],
410 TOXAV_CALL_STATE_ERROR, toxav->scb.second);
411}
412
413void i_toxav_msi_callback_state_change(void* toxav_inst, int32_t call_idx, void* data)
414{
415 ToxAV* toxav = toxav_inst;
416 /* TODO something something msi */
417}
418
419IToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number)
420{
421 if (av->calls_tail < friend_number)
422 return NULL;
423
424 return av->calls[friend_number];
425}
426
427IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
428{
429 IToxAVCall* rc = calloc(sizeof(IToxAVCall), 1);
430
431 if (rc == NULL)
432 return NULL;
433
434 rc->friend_number = friend_number;
435
436 if (create_recursive_mutex(rc->mutex_control) != 0) {
437 free(rc);
438 return NULL;
439 }
440
441 if (create_recursive_mutex(rc->mutex_do) != 0) {
442 pthread_mutex_destroy(rc->mutex_control);
443 free(rc);
444 return NULL;
445 }
446
447
448 if (av->calls == NULL) { /* Creating */
449 av->calls = calloc (sizeof(IToxAVCall*), friend_number + 1);
450
451 if (av->calls == NULL) {
452 pthread_mutex_destroy(rc->mutex_control);
453 pthread_mutex_destroy(rc->mutex_do);
454 free(rc);
455 return NULL;
456 }
457
458 av->calls_tail = av->calls_head = friend_number;
459
460 } else if (av->calls_tail < friend_number) { /* Appending */
461 void* tmp = realloc(av->calls, sizeof(IToxAVCall*) * friend_number + 1);
462
463 if (tmp == NULL) {
464 pthread_mutex_destroy(rc->mutex_control);
465 pthread_mutex_destroy(rc->mutex_do);
466 free(rc);
467 return NULL;
468 }
469
470 av->calls = tmp;
471
472 /* Set fields in between to null */
473 int32_t i = av->calls_tail;
474 for (; i < friend_number; i ++)
475 av->calls[i] = NULL;
476
477 rc->prev = av->calls[av->calls_tail];
478 av->calls[av->calls_tail]->next = rc;
479
480 av->calls_tail = friend_number;
481
482 } else if (av->calls_head > friend_number) { /* Inserting at front */
483 rc->next = av->calls[av->calls_head];
484 av->calls[av->calls_head]->prev = rc;
485 av->calls_head = friend_number;
486 }
487
488 av->calls[friend_number] = rc;
489 return rc;
490}
491
492void i_toxav_remove_call(ToxAV* av, uint32_t friend_number)
493{
494 IToxAVCall* tc = i_toxav_get_call(av, friend_number);
495
496 if (tc == NULL)
497 return;
498
499 IToxAVCall* prev = tc->prev;
500 IToxAVCall* next = tc->next;
501
502 pthread_mutex_destroy(tc->mutex_control);
503 pthread_mutex_destroy(tc->mutex_do);
504
505 free(tc);
506
507 if (prev)
508 prev->next = next;
509 else if (next)
510 av->calls_head = next->friend_number;
511 else goto CLEAR;
512
513 if (next)
514 next->prev = prev;
515 else if (prev)
516 av->calls_tail = prev->friend_number;
517 else goto CLEAR;
518
519 av->calls[friend_number] = NULL;
520 return;
521
522CLEAR:
523 av->calls_head = av->calls_tail = 0;
524 free(av->calls);
525 av->calls = NULL;
526}
527
528bool i_toxav_audio_bitrate_invalid(uint32_t bitrate)
529{
530 /* Opus RFC 6716 section-2.1.1 dictates the following:
531 * Opus supports all bitrates from 6 kbit/s to 510 kbit/s.
532 */
533 return bitrate < 6 || bitrate > 510;
534}
535
536bool i_toxav_video_bitrate_invalid(uint32_t bitrate)
537{
538 /* TODO: If anyone knows the answer to this one please fill it up */
539 return false;
540}
541
542IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error)
543{
544 TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK;
545 IToxAVCall* call = NULL;
546
547 if (m_friend_exists(av->m, friend_number)) {
548 rc = TOXAV_ERR_CALL_FRIEND_NOT_FOUND;
549 goto END;
550 }
551
552 if (m_get_friend_connectionstatus(av->m, friend_number) != 1) {
553 rc = TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED;
554 goto END;
555 }
556
557 if (i_toxav_get_call(av, friend_number) != NULL) {
558 rc = TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL;
559 goto END;
560 }
561
562 if ((audio_bit_rate && i_toxav_audio_bitrate_invalid(audio_bit_rate))
563 ||(video_bit_rate && i_toxav_video_bitrate_invalid(video_bit_rate))
564 ) {
565 rc = TOXAV_ERR_CALL_INVALID_BIT_RATE;
566 goto END;
567 }
568
569 IToxAVCall* call = i_toxav_add_call(av, friend_number);
570 if (call == NULL) {
571 rc = TOXAV_ERR_CALL_MALLOC;
572 }
573
574END:
575 if (error)
576 *error = rc;
577
578 return call;
579}
580
581bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call)
582{
583 pthread_mutex_lock(call->mutex_control);
584
585 if (call->active) {
586 pthread_mutex_unlock(call->mutex_control);
587 LOGGER_WARNING("Call already active!\n");
588 return true;
589 }
590
591 if (pthread_mutex_init(call->mutex_encoding_audio, NULL) != 0)
592 goto MUTEX_INIT_ERROR;
593
594 if (pthread_mutex_init(call->mutex_encoding_video, NULL) != 0) {
595 pthread_mutex_destroy(call->mutex_encoding_audio);
596 goto MUTEX_INIT_ERROR;
597 }
598
599 if (pthread_mutex_init(call->mutex_do, NULL) != 0) {
600 pthread_mutex_destroy(call->mutex_encoding_audio);
601 pthread_mutex_destroy(call->mutex_encoding_video);
602 goto MUTEX_INIT_ERROR;
603 }
604
605 const MSICSettings *c_peer = &av->msi->calls[call->call_idx]->csettings_peer[0];
606 const MSICSettings *c_self = &av->msi->calls[call->call_idx]->csettings_local;
607
608 call->cs = cs_new(c_self->audio_bitrate, c_peer->audio_bitrate,
609 c_self->video_bitrate, c_peer->video_bitrate);
610
611 if ( !call->cs ) {
612 LOGGER_ERROR("Error while starting Codec State!\n");
613 goto FAILURE;
614 }
615
616 call->cs->agent = av;
617 call->cs->call_idx = call->call_idx;
618
619 call->cs->acb.first = av->acb.first;
620 call->cs->acb.second = av->acb.second;
621
622 call->cs->vcb.first = av->vcb.first;
623 call->cs->vcb.second = av->vcb.second;
624
625
626 if (c_self->audio_bitrate > 0 || c_peer->audio_bitrate > 0) { /* Prepare audio rtp */
627 call->rtps[audio_index] = rtp_new(msi_TypeAudio, av->m, av->msi->calls[call->call_idx]->peers[0]);
628
629 if ( !call->rtps[audio_index] ) {
630 LOGGER_ERROR("Error while starting audio RTP session!\n");
631 goto FAILURE;
632 }
633
634 call->rtps[audio_index]->cs = call->cs;
635
636 if (c_peer->audio_bitrate > 0)
637 rtp_register_for_receiving(call->rtps[audio_index]);
638 }
639
640 if (c_self->video_bitrate > 0 || c_peer->video_bitrate > 0) { /* Prepare video rtp */
641 call->rtps[video_index] = rtp_new(msi_TypeVideo, av->m, av->msi->calls[call->call_idx]->peers[0]);
642
643 if ( !call->rtps[video_index] ) {
644 LOGGER_ERROR("Error while starting video RTP session!\n");
645 goto FAILURE;
646 }
647
648 call->rtps[video_index]->cs = call->cs;
649
650 if (c_peer->video_bitrate > 0)
651 rtp_register_for_receiving(call->rtps[audio_index]);
652 }
653
654 call->active = 1;
655 pthread_mutex_unlock(call->mutex_control);
656 return true;
657
658FAILURE:
659 rtp_kill(call->rtps[audio_index]);
660 call->rtps[audio_index] = NULL;
661 rtp_kill(call->rtps[video_index]);
662 call->rtps[video_index] = NULL;
663 cs_kill(call->cs);
664 call->cs = NULL;
665 call->active = 0;
666 pthread_mutex_destroy(call->mutex_encoding_audio);
667 pthread_mutex_destroy(call->mutex_encoding_video);
668 pthread_mutex_destroy(call->mutex_do);
669
670 pthread_mutex_unlock(call->mutex_control);
671 return false;
672
673MUTEX_INIT_ERROR:
674 pthread_mutex_unlock(call->mutex_control);
675 LOGGER_ERROR("Mutex initialization failed!\n");
676 return false;
677}
678
679void i_toxav_kill_transmission(ToxAV* av, IToxAVCall* call)
680{
681 pthread_mutex_lock(call->mutex_control);
682
683 if (!call->active) {
684 pthread_mutex_unlock(call->mutex_control);
685 LOGGER_WARNING("Action on inactive call: %d", call->call_idx);
686 return;
687 }
688
689 call->active = 0;
690
691 pthread_mutex_lock(call->mutex_encoding_audio);
692 pthread_mutex_unlock(call->mutex_encoding_audio);
693 pthread_mutex_lock(call->mutex_encoding_video);
694 pthread_mutex_unlock(call->mutex_encoding_video);
695 pthread_mutex_lock(call->mutex_do);
696 pthread_mutex_unlock(call->mutex_do);
697
698 rtp_kill(call->rtps[audio_index]);
699 call->rtps[audio_index] = NULL;
700 rtp_kill(call->rtps[video_index]);
701 call->rtps[video_index] = NULL;
702 cs_kill(call->cs);
703 call->cs = NULL;
704
705 pthread_mutex_destroy(call->mutex_encoding_audio);
706 pthread_mutex_destroy(call->mutex_encoding_video);
707 pthread_mutex_destroy(call->mutex_do);
708
709 pthread_mutex_unlock(call->mutex_control);
710}