summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toxav/codec.c57
-rw-r--r--toxav/codec.h10
-rw-r--r--toxav/msi.c111
-rw-r--r--toxav/msi.h12
-rw-r--r--toxav/toxav.c188
-rw-r--r--toxav/toxav_new_1.c1
6 files changed, 154 insertions, 225 deletions
diff --git a/toxav/codec.c b/toxav/codec.c
index 9fc14071..e44387df 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -44,9 +44,7 @@
44#define MAX_ENCODE_TIME_US VPX_DL_GOOD_QUALITY 44#define MAX_ENCODE_TIME_US VPX_DL_GOOD_QUALITY
45#define MAX_DECODE_TIME_US 0 45#define MAX_DECODE_TIME_US 0
46 46
47// TODO this has to be exchanged in msi
48#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */ 47#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */
49#define VIDEOFRAME_PIECE_SIZE 0x500 /* 1.25 KiB*/
50#define VIDEOFRAME_HEADER_SIZE 0x2 48#define VIDEOFRAME_HEADER_SIZE 0x2
51 49
52/* FIXME: Might not be enough */ 50/* FIXME: Might not be enough */
@@ -296,7 +294,7 @@ void cs_do(CSSession *cs)
296 LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); 294 LOGGER_WARNING("Decoding error: %s", opus_strerror(rc));
297 } else if (cs->acb.first) { 295 } else if (cs->acb.first) {
298 /* Play */ 296 /* Play */
299 cs->acb.first(cs->agent, cs->friend_number, tmp, rc, 297 cs->acb.first(cs->agent, cs->friend_id, tmp, rc,
300 cs->last_pack_channels, cs->last_packet_sampling_rate, cs->acb.second); 298 cs->last_pack_channels, cs->last_packet_sampling_rate, cs->acb.second);
301 } 299 }
302 300
@@ -323,7 +321,7 @@ void cs_do(CSSession *cs)
323 /* Play decoded images */ 321 /* Play decoded images */
324 for (; dest; dest = vpx_codec_get_frame(cs->v_decoder, &iter)) { 322 for (; dest; dest = vpx_codec_get_frame(cs->v_decoder, &iter)) {
325 if (cs->vcb.first) 323 if (cs->vcb.first)
326 cs->vcb.first(cs->agent, cs->call_idx, dest->d_w, dest->d_h, 324 cs->vcb.first(cs->agent, cs->friend_id, dest->d_w, dest->d_h,
327 (const uint8_t**)dest->planes, dest->stride, cs->vcb.second); 325 (const uint8_t**)dest->planes, dest->stride, cs->vcb.second);
328 326
329 vpx_img_free(dest); 327 vpx_img_free(dest);
@@ -336,7 +334,7 @@ void cs_do(CSSession *cs)
336 pthread_mutex_unlock(cs->queue_mutex); 334 pthread_mutex_unlock(cs->queue_mutex);
337} 335}
338 336
339CSSession *cs_new(uint32_t s_audio_b, uint32_t p_audio_b, uint32_t s_video_b, uint32_t p_video_b) 337CSSession *cs_new(uint32_t peer_video_frame_piece_size)
340{ 338{
341 CSSession *cs = calloc(sizeof(CSSession), 1); 339 CSSession *cs = calloc(sizeof(CSSession), 1);
342 340
@@ -345,29 +343,7 @@ CSSession *cs_new(uint32_t s_audio_b, uint32_t p_audio_b, uint32_t s_video_b, ui
345 return NULL; 343 return NULL;
346 } 344 }
347 345
348 /* TODO this has to be exchanged in msi */ 346 cs->peer_video_frame_piece_size = peer_video_frame_piece_size;
349 cs->max_video_frame_size = MAX_VIDEOFRAME_SIZE;
350 cs->video_frame_piece_size = VIDEOFRAME_PIECE_SIZE;
351
352 if (s_audio_b > 0 && 0 != cs_enable_audio_sending(cs, s_audio_b, 2)) { /* Sending audio enabled */
353 LOGGER_WARNING("Failed to enable audio sending!");
354 goto FAILURE;
355 }
356
357 if (p_audio_b > 0 && 0 != cs_enable_audio_receiving(cs)) { /* Receiving audio enabled */
358 LOGGER_WARNING("Failed to enable audio receiving!");
359 goto FAILURE;
360 }
361
362 if (s_video_b > 0 && 0 != cs_enable_video_sending(cs, s_video_b)) { /* Sending video enabled */
363 LOGGER_WARNING("Failed to enable video sending!");
364 goto FAILURE;
365 }
366
367 if (p_video_b > 0 && 0 != cs_enable_video_receiving(cs)) { /* Receiving video enabled */
368 LOGGER_WARNING("Failed to enable video receiving!");
369 goto FAILURE;
370 }
371 347
372 return cs; 348 return cs;
373 349
@@ -415,22 +391,22 @@ int cs_update_video_splitter_cycle(CSSession *cs, const uint8_t *payload, uint16
415 cs->processing_video_frame = payload; 391 cs->processing_video_frame = payload;
416 cs->processing_video_frame_size = length; 392 cs->processing_video_frame_size = length;
417 393
418 return ((length - 1) / cs->video_frame_piece_size) + 1; 394 return ((length - 1) / VIDEOFRAME_PIECE_SIZE) + 1;
419} 395}
420 396
421const uint8_t *cs_iterate_split_video_frame(CSSession *cs, uint16_t *size) 397const uint8_t *cs_iterate_split_video_frame(CSSession *cs, uint16_t *size)
422{ 398{
423 if (!cs || !size) return NULL; 399 if (!cs || !size) return NULL;
424 400
425 if (cs->processing_video_frame_size > cs->video_frame_piece_size) { 401 if (cs->processing_video_frame_size > VIDEOFRAME_PIECE_SIZE) {
426 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE, 402 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE,
427 cs->processing_video_frame, 403 cs->processing_video_frame,
428 cs->video_frame_piece_size); 404 VIDEOFRAME_PIECE_SIZE);
429 405
430 cs->processing_video_frame += cs->video_frame_piece_size; 406 cs->processing_video_frame += VIDEOFRAME_PIECE_SIZE;
431 cs->processing_video_frame_size -= cs->video_frame_piece_size; 407 cs->processing_video_frame_size -= VIDEOFRAME_PIECE_SIZE;
432 408
433 *size = cs->video_frame_piece_size + VIDEOFRAME_HEADER_SIZE; 409 *size = VIDEOFRAME_PIECE_SIZE + VIDEOFRAME_HEADER_SIZE;
434 } else { 410 } else {
435 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE, 411 memcpy(cs->split_video_frame + VIDEOFRAME_HEADER_SIZE,
436 cs->processing_video_frame, 412 cs->processing_video_frame,
@@ -492,7 +468,7 @@ int cs_set_sending_video_bitrate(CSSession *cs, uint32_t bitrate)
492 if (cfg.rc_target_bitrate == bitrate) 468 if (cfg.rc_target_bitrate == bitrate)
493 return 0; 469 return 0;
494 470
495 LOGGER_DEBUG("New video bitrate: %u", video_bitrate); 471 LOGGER_DEBUG("New video bitrate: %u", bitrate);
496 cfg.rc_target_bitrate = bitrate; 472 cfg.rc_target_bitrate = bitrate;
497 473
498 int rc = vpx_codec_enc_config_set(cs->v_encoder, &cfg); 474 int rc = vpx_codec_enc_config_set(cs->v_encoder, &cfg);
@@ -528,7 +504,7 @@ int cs_enable_video_sending(CSSession* cs, uint32_t bitrate)
528 /* So that we can use cs_disable_video_sending to clean up */ 504 /* So that we can use cs_disable_video_sending to clean up */
529 cs->v_encoding = true; 505 cs->v_encoding = true;
530 506
531 if ( !(cs->split_video_frame = calloc(cs->video_frame_piece_size + VIDEOFRAME_HEADER_SIZE, 1)) ) 507 if ( !(cs->split_video_frame = calloc(VIDEOFRAME_PIECE_SIZE + VIDEOFRAME_HEADER_SIZE, 1)) )
532 goto FAILURE; 508 goto FAILURE;
533 509
534 cfg.rc_target_bitrate = bitrate; 510 cfg.rc_target_bitrate = bitrate;
@@ -579,7 +555,7 @@ int cs_enable_video_receiving(CSSession* cs)
579 /* So that we can use cs_disable_video_sending to clean up */ 555 /* So that we can use cs_disable_video_sending to clean up */
580 cs->v_decoding = true; 556 cs->v_decoding = true;
581 557
582 if ( !(cs->frame_buf = calloc(cs->max_video_frame_size, 1)) ) 558 if ( !(cs->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1)) )
583 goto FAILURE; 559 goto FAILURE;
584 560
585 if ( !(cs->vbuf_raw = buffer_new(VIDEO_DECODE_BUFFER_SIZE)) ) 561 if ( !(cs->vbuf_raw = buffer_new(VIDEO_DECODE_BUFFER_SIZE)) )
@@ -837,10 +813,10 @@ void queue_message(RTPSession *session, RTPMessage *msg)
837 813
838 uint8_t piece_number = packet[1]; 814 uint8_t piece_number = packet[1];
839 815
840 uint32_t length_before_piece = ((piece_number - 1) * cs->video_frame_piece_size); 816 uint32_t length_before_piece = ((piece_number - 1) * cs->peer_video_frame_piece_size);
841 uint32_t framebuf_new_length = length_before_piece + (packet_size - VIDEOFRAME_HEADER_SIZE); 817 uint32_t framebuf_new_length = length_before_piece + (packet_size - VIDEOFRAME_HEADER_SIZE);
842 818
843 if (framebuf_new_length > cs->max_video_frame_size) { 819 if (framebuf_new_length > MAX_VIDEOFRAME_SIZE) {
844 goto end; 820 goto end;
845 } 821 }
846 822
@@ -851,9 +827,8 @@ void queue_message(RTPSession *session, RTPMessage *msg)
851 packet + VIDEOFRAME_HEADER_SIZE, 827 packet + VIDEOFRAME_HEADER_SIZE,
852 packet_size - VIDEOFRAME_HEADER_SIZE); 828 packet_size - VIDEOFRAME_HEADER_SIZE);
853 829
854 if (framebuf_new_length > cs->frame_size) { 830 if (framebuf_new_length > cs->frame_size)
855 cs->frame_size = framebuf_new_length; 831 cs->frame_size = framebuf_new_length;
856 }
857 832
858end: 833end:
859 rtp_free_msg(NULL, msg); 834 rtp_free_msg(NULL, msg);
diff --git a/toxav/codec.h b/toxav/codec.h
index b5eb19e2..6a673990 100644
--- a/toxav/codec.h
+++ b/toxav/codec.h
@@ -86,13 +86,12 @@ typedef struct CSSession_s {
86 86
87 /* Data handling */ 87 /* Data handling */
88 uint8_t *frame_buf; /* buffer for split video payloads */ 88 uint8_t *frame_buf; /* buffer for split video payloads */
89 uint32_t frame_size; /* largest address written to in frame_buf for current input frame*/ 89 uint32_t frame_size; /* largest address written to in frame_buf for current input frame */
90 uint8_t frameid_in, frameid_out; /* id of input and output video frame */ 90 uint8_t frameid_in, frameid_out; /* id of input and output video frame */
91 uint32_t last_timestamp; /* calculating cycles */ 91 uint32_t last_timestamp; /* calculating cycles */
92 92
93 /* Limits */ 93 /* Limits */
94 uint32_t video_frame_piece_size; 94 uint32_t peer_video_frame_piece_size;
95 uint32_t max_video_frame_size;
96 95
97 /* Splitting */ 96 /* Splitting */
98 uint8_t *split_video_frame; 97 uint8_t *split_video_frame;
@@ -129,8 +128,7 @@ typedef struct CSSession_s {
129 * 128 *
130 */ 129 */
131 void *agent; /* Pointer to ToxAV TODO make this pointer to ToxAV*/ 130 void *agent; /* Pointer to ToxAV TODO make this pointer to ToxAV*/
132 int32_t call_idx; 131 int32_t friend_id;
133 int32_t friend_number;
134 132
135 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ 133 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */
136 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ 134 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */
@@ -145,7 +143,7 @@ typedef struct CSSession_s {
145void cs_do(CSSession *cs); 143void cs_do(CSSession *cs);
146 144
147/* Make sure to be called BEFORE corresponding rtp_new */ 145/* Make sure to be called BEFORE corresponding rtp_new */
148CSSession *cs_new(uint32_t s_audio_b, uint32_t p_audio_b, uint32_t s_video_b, uint32_t p_video_b); 146CSSession *cs_new(uint32_t peer_mvfpsz);
149/* Make sure to be called AFTER corresponding rtp_kill */ 147/* Make sure to be called AFTER corresponding rtp_kill */
150void cs_kill(CSSession *cs); 148void cs_kill(CSSession *cs);
151 149
diff --git a/toxav/msi.c b/toxav/msi.c
index cc855613..16476364 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -50,8 +50,7 @@ typedef enum {
50 IDResponse, 50 IDResponse,
51 IDError, 51 IDError,
52 IDCapabilities, 52 IDCapabilities,
53 IDMVFSZ, 53 IDVFPSZ,
54 IDMVFPSZ,
55 54
56} MSIHeaderID; 55} MSIHeaderID;
57 56
@@ -79,8 +78,7 @@ GENERIC_HEADER ( Request, MSIRequest );
79GENERIC_HEADER ( Response, MSIResponse ); 78GENERIC_HEADER ( Response, MSIResponse );
80GENERIC_HEADER ( Error, MSIError ); 79GENERIC_HEADER ( Error, MSIError );
81GENERIC_HEADER ( Capabilities, uint8_t ); 80GENERIC_HEADER ( Capabilities, uint8_t );
82GENERIC_HEADER ( MVFSZ, uint16_t ); 81GENERIC_HEADER ( VFPSZ, uint16_t );
83GENERIC_HEADER ( MVFPSZ, uint16_t );
84 82
85 83
86typedef struct { 84typedef struct {
@@ -88,8 +86,7 @@ typedef struct {
88 MSIHeaderResponse response; 86 MSIHeaderResponse response;
89 MSIHeaderError error; 87 MSIHeaderError error;
90 MSIHeaderCapabilities capabilities; 88 MSIHeaderCapabilities capabilities;
91 MSIHeaderMVFSZ mvfsz; /* Max video frame size. NOTE: Value must be in network b-order */ 89 MSIHeaderVFPSZ vfpsz; /* Video frame piece size. NOTE: Value must be in network b-order */
92 MSIHeaderMVFPSZ mvfpsz; /* Max video frame piece size. NOTE: Value must be in network b-order */
93} MSIMessage; 90} MSIMessage;
94 91
95 92
@@ -200,12 +197,9 @@ int msi_invite ( MSISession *session, MSICall **call, uint32_t friend_id, uint8_
200 197
201 msg_invite.capabilities.exists = true; 198 msg_invite.capabilities.exists = true;
202 msg_invite.capabilities.value = capabilities; 199 msg_invite.capabilities.value = capabilities;
203 200
204 msg_invite.mvfsz.exists = true; 201 msg_invite.vfpsz.exists = true;
205 msg_invite.mvfsz.value = htons(D_MVFSZ); 202 msg_invite.vfpsz.value = htons(VIDEOFRAME_PIECE_SIZE);
206
207 msg_invite.mvfpsz.exists = true;
208 msg_invite.mvfpsz.value = htons(D_MVFPSZ);
209 203
210 send_message ( (*call)->session->messenger, (*call)->friend_id, &msg_invite ); 204 send_message ( (*call)->session->messenger, (*call)->friend_id, &msg_invite );
211 205
@@ -216,7 +210,7 @@ int msi_invite ( MSISession *session, MSICall **call, uint32_t friend_id, uint8_
216} 210}
217int msi_hangup ( MSICall* call ) 211int msi_hangup ( MSICall* call )
218{ 212{
219 LOGGER_DEBUG("Session: %p Hanging up call: %u", session, call_index); 213 LOGGER_DEBUG("Session: %p Hanging up call with friend: %u", call->session, call->friend_id);
220 214
221 MSIMessage msg_end; 215 MSIMessage msg_end;
222 msg_end.request.exists = true; 216 msg_end.request.exists = true;
@@ -244,11 +238,8 @@ int msi_answer ( MSICall* call, uint8_t capabilities )
244 msg_starting.capabilities.exists = true; 238 msg_starting.capabilities.exists = true;
245 msg_starting.capabilities.value = capabilities; 239 msg_starting.capabilities.value = capabilities;
246 240
247 msg_starting.mvfsz.exists = true; 241 msg_starting.vfpsz.exists = true;
248 msg_starting.mvfsz.value = htons(D_MVFSZ); 242 msg_starting.vfpsz.value = htons(VIDEOFRAME_PIECE_SIZE);
249
250 msg_starting.mvfpsz.exists = true;
251 msg_starting.mvfpsz.value = htons(D_MVFPSZ);
252 243
253 send_message ( call->session->messenger, call->friend_id, &msg_starting ); 244 send_message ( call->session->messenger, call->friend_id, &msg_starting );
254 245
@@ -256,7 +247,7 @@ int msi_answer ( MSICall* call, uint8_t capabilities )
256} 247}
257int msi_reject ( MSICall* call ) 248int msi_reject ( MSICall* call )
258{ 249{
259 LOGGER_DEBUG("Session: %p Rejecting call: %u; reason: %s", session, call_index, reason ? reason : "Unknown"); 250 LOGGER_DEBUG("Session: %p Rejecting call with friend: %u", call->session, call->friend_id);
260 251
261 if ( call->state != msi_CallRequested ) { 252 if ( call->state != msi_CallRequested ) {
262 LOGGER_ERROR("Call is in invalid state!"); 253 LOGGER_ERROR("Call is in invalid state!");
@@ -353,14 +344,9 @@ int msg_parse_in ( MSIMessage *dest, const uint8_t *data, uint16_t length )
353 SET_UINT8(it, dest->capabilities); 344 SET_UINT8(it, dest->capabilities);
354 break; 345 break;
355 346
356 case IDMVFSZ: 347 case IDVFPSZ:
357 CHECK_SIZE(it, size_constraint, 2);
358 SET_UINT16(it, dest->mvfsz);
359 break;
360
361 case IDMVFPSZ:
362 CHECK_SIZE(it, size_constraint, 2); 348 CHECK_SIZE(it, size_constraint, 2);
363 SET_UINT16(it, dest->mvfpsz); 349 SET_UINT16(it, dest->vfpsz);
364 break; 350 break;
365 351
366 default: 352 default:
@@ -408,33 +394,28 @@ int send_message ( Messenger* m, uint32_t friend_id, const MSIMessage *msg )
408 if (msg->request.exists) { 394 if (msg->request.exists) {
409 uint8_t cast = msg->request.value; 395 uint8_t cast = msg->request.value;
410 it = msg_parse_header_out(IDRequest, it, &cast, 396 it = msg_parse_header_out(IDRequest, it, &cast,
411 sizeof(cast), &size); 397 sizeof(cast), &size);
412 } 398 }
413 399
414 if (msg->response.exists) { 400 if (msg->response.exists) {
415 uint8_t cast = msg->response.value; 401 uint8_t cast = msg->response.value;
416 it = msg_parse_header_out(IDResponse, it, &cast, 402 it = msg_parse_header_out(IDResponse, it, &cast,
417 sizeof(cast), &size); 403 sizeof(cast), &size);
418 } 404 }
419 405
420 if (msg->error.exists) { 406 if (msg->error.exists) {
421 it = msg_parse_header_out(IDError, it, &msg->error.value, 407 it = msg_parse_header_out(IDError, it, &msg->error.value,
422 sizeof(msg->error.value), &size); 408 sizeof(msg->error.value), &size);
423 } 409 }
424 410
425 if (msg->capabilities.exists) { 411 if (msg->capabilities.exists) {
426 it = msg_parse_header_out(IDCapabilities, it, &msg->capabilities.value, 412 it = msg_parse_header_out(IDCapabilities, it, &msg->capabilities.value,
427 sizeof(msg->capabilities.value), &size); 413 sizeof(msg->capabilities.value), &size);
428 } 414 }
429 415
430 if (msg->mvfsz.exists) { 416 if (msg->vfpsz.exists) {
431 it = msg_parse_header_out(IDMVFSZ, it, &msg->mvfsz.value, 417 it = msg_parse_header_out(IDVFPSZ, it, &msg->vfpsz.value,
432 sizeof(msg->mvfsz.value), &size); 418 sizeof(msg->vfpsz.value), &size);
433 }
434
435 if (msg->mvfpsz.exists) {
436 it = msg_parse_header_out(IDMVFPSZ, it, &msg->mvfpsz.value,
437 sizeof(msg->mvfpsz.value), &size);
438 } 419 }
439 420
440 *it = 0; 421 *it = 0;
@@ -494,6 +475,7 @@ MSICall *new_call ( MSISession *session, uint32_t friend_id )
494 if (rc == NULL) 475 if (rc == NULL)
495 return NULL; 476 return NULL;
496 477
478 rc->session = session;
497 rc->friend_id = friend_id; 479 rc->friend_id = friend_id;
498 480
499 if (session->calls == NULL) { /* Creating */ 481 if (session->calls == NULL) { /* Creating */
@@ -617,28 +599,14 @@ int handle_recv_invite ( MSICall *call, const MSIMessage *msg )
617 599
618 LOGGER_DEBUG("Glare detected!"); 600 LOGGER_DEBUG("Glare detected!");
619 601
620 if (!msg->mvfsz.exists) { 602 if (!msg->vfpsz.exists) {
621 LOGGER_WARNING("Session: %p Invalid mvfsz on 'invite'");
622 call->error = msi_InvalidMessage;
623 return -1;
624 }
625
626 if (!msg->mvfpsz.exists) {
627 LOGGER_WARNING("Session: %p Invalid mvfpsz on 'invite'"); 603 LOGGER_WARNING("Session: %p Invalid mvfpsz on 'invite'");
628 call->error = msi_InvalidMessage; 604 call->error = msi_InvalidMessage;
629 return -1; 605 return -1;
630 } 606 }
631 607
632 call->peer_capabilities = msg->capabilities.value; 608 call->peer_capabilities = msg->capabilities.value;
633 609 call->peer_vfpsz = ntohs(msg->vfpsz.value);
634 call->peer_mvfsz = ntohs(msg->mvfsz.value);
635 call->peer_mvfpsz = ntohs(msg->mvfpsz.value);
636
637 if (call->peer_mvfsz > call->peer_mvfpsz) {
638 LOGGER_WARNING("Session: %p mvfsz param greater than mvfpsz on 'invite'");
639 call->error = msi_InvalidParam;
640 return -1;
641 }
642 610
643 /* Send response */ 611 /* Send response */
644 response.response.value = resp_starting; 612 response.response.value = resp_starting;
@@ -665,24 +633,14 @@ int handle_recv_invite ( MSICall *call, const MSIMessage *msg )
665 return 0; 633 return 0;
666 } 634 }
667 635
668 636 if (!msg->vfpsz.exists) {
669 if (!msg->mvfsz.exists) {
670 LOGGER_WARNING("Session: %p Invalid mvfsz on 'invite'");
671 call->error = msi_InvalidMessage;
672 return -1;
673 }
674
675 if (!msg->mvfpsz.exists) {
676 LOGGER_WARNING("Session: %p Invalid mvfpsz on 'invite'"); 637 LOGGER_WARNING("Session: %p Invalid mvfpsz on 'invite'");
677 call->error = msi_InvalidMessage; 638 call->error = msi_InvalidMessage;
678 return -1; 639 return -1;
679 } 640 }
680 641
681 call->peer_capabilities = msg->capabilities.value; 642 call->peer_capabilities = msg->capabilities.value;
682 643 call->peer_vfpsz = ntohs(msg->vfpsz.value);
683 call->peer_mvfsz = ntohs(msg->mvfsz.value);
684 call->peer_mvfpsz = ntohs(msg->mvfpsz.value);
685
686 call->state = msi_CallRequested; 644 call->state = msi_CallRequested;
687 645
688 /* Send response */ 646 /* Send response */
@@ -781,31 +739,16 @@ int handle_recv_starting ( MSICall *call, const MSIMessage *msg )
781 return -1; 739 return -1;
782 } 740 }
783 741
784 if (!msg->mvfsz.exists) { 742 if (!msg->vfpsz.exists) {
785 LOGGER_WARNING("Session: %p Invalid mvfsz on 'invite'");
786 call->error = msi_InvalidParam;
787 return -1;
788 }
789
790 if (!msg->mvfpsz.exists) {
791 LOGGER_WARNING("Session: %p Invalid mvfpsz on 'invite'"); 743 LOGGER_WARNING("Session: %p Invalid mvfpsz on 'invite'");
792 call->error = msi_InvalidParam; 744 call->error = msi_InvalidParam;
793 return -1; 745 return -1;
794 } 746 }
795 747
796 call->peer_capabilities = msg->capabilities.value; 748 call->peer_capabilities = msg->capabilities.value;
797 749 call->peer_vfpsz = ntohs(msg->vfpsz.value);
798 call->peer_mvfsz = ntohs(msg->mvfsz.value);
799 call->peer_mvfpsz = ntohs(msg->mvfpsz.value);
800
801
802 if (call->peer_mvfsz > call->peer_mvfpsz) {
803 LOGGER_WARNING("Session: %p mvfsz param greater than mvfpsz on 'invite'");
804 call->error = msi_InvalidParam;
805 return -1;
806 }
807
808 call->state = msi_CallActive; 750 call->state = msi_CallActive;
751
809 invoke_callback(call, msi_OnStart); 752 invoke_callback(call, msi_OnStart);
810 } 753 }
811 /* Otherwise it's a glare case so don't start until 'start' is recved */ 754 /* Otherwise it's a glare case so don't start until 'start' is recved */
diff --git a/toxav/msi.h b/toxav/msi.h
index 4f27b9f8..a55d8567 100644
--- a/toxav/msi.h
+++ b/toxav/msi.h
@@ -28,9 +28,8 @@
28#include "codec.h" 28#include "codec.h"
29#include "../toxcore/Messenger.h" 29#include "../toxcore/Messenger.h"
30 30
31/** Preconfigured values for video splitting */ 31/** Preconfigured value for video splitting */
32#define D_MVFSZ 40000 /* 256KiB */ 32#define VIDEOFRAME_PIECE_SIZE 500 /* 1.25 KiB*/
33#define D_MVFPSZ 500 /* 1.25 KiB*/
34 33
35/** 34/**
36 * Error codes. 35 * Error codes.
@@ -87,15 +86,10 @@ typedef struct MSICall_s {
87 struct MSISession_s *session; /* Session pointer */ 86 struct MSISession_s *session; /* Session pointer */
88 87
89 MSICallState state; 88 MSICallState state;
90
91 uint8_t peer_capabilities; /* Peer capabilities */ 89 uint8_t peer_capabilities; /* Peer capabilities */
92 uint8_t self_capabilities; /* Self capabilities */ 90 uint8_t self_capabilities; /* Self capabilities */
93 91 uint16_t peer_vfpsz; /* Video frame piece size */
94 uint16_t peer_mvfsz; /* Max video frame size */
95 uint16_t peer_mvfpsz; /* Max video frame part size */
96
97 uint32_t friend_id; /* Index of this call in MSISession */ 92 uint32_t friend_id; /* Index of this call in MSISession */
98
99 MSIError error; /* Last error */ 93 MSIError error; /* Last error */
100 94
101 void* av_call; /* Pointer to av call handler */ 95 void* av_call; /* Pointer to av call handler */
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 12a65737..584b3898 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -40,21 +40,24 @@ enum {
40 video_index, 40 video_index,
41}; 41};
42 42
43typedef struct iToxAVCall 43typedef struct ToxAVCall_s
44{ 44{
45 pthread_mutex_t mutex_control[1]; 45 pthread_mutex_t mutex_control[1];
46 pthread_mutex_t mutex_encoding_audio[1]; 46 pthread_mutex_t mutex_encoding_audio[1];
47 pthread_mutex_t mutex_encoding_video[1]; 47 pthread_mutex_t mutex_encoding_video[1];
48 pthread_mutex_t mutex_do[1]; 48 pthread_mutex_t mutex_do[1];
49 RTPSession *rtps[2]; /** Audio is first and video is second */ 49 RTPSession *rtps[2]; /* Audio is first and video is second */
50 CSSession *cs; 50 CSSession *cs;
51 bool active; 51 bool active;
52 int32_t friend_id;
53 MSICall* msi_call; 52 MSICall* msi_call;
53 uint32_t friend_id;
54 54
55 struct iToxAVCall *prev; 55 uint32_t s_audio_b; /* Sending audio bitrate */
56 struct iToxAVCall *next; 56 uint32_t s_video_b; /* Sending video bitrate */
57} IToxAVCall; 57
58 struct ToxAVCall_s *prev;
59 struct ToxAVCall_s *next;
60} ToxAVCall;
58 61
59struct toxAV 62struct toxAV
60{ 63{
@@ -62,7 +65,7 @@ struct toxAV
62 MSISession* msi; 65 MSISession* msi;
63 66
64 /* Two-way storage: first is array of calls and second is list of calls with head and tail */ 67 /* Two-way storage: first is array of calls and second is list of calls with head and tail */
65 IToxAVCall** calls; 68 ToxAVCall** calls;
66 uint32_t calls_tail; 69 uint32_t calls_tail;
67 uint32_t calls_head; 70 uint32_t calls_head;
68 71
@@ -88,13 +91,13 @@ void i_callback_error(void* toxav_inst, MSICall* call);
88void i_callback_capabilites(void* toxav_inst, MSICall* call); 91void i_callback_capabilites(void* toxav_inst, MSICall* call);
89 92
90TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities); 93TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities);
91IToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number); 94ToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number);
92IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number); 95ToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number);
93void i_toxav_remove_call(ToxAV* av, uint32_t friend_number); 96void i_toxav_remove_call(ToxAV* av, uint32_t friend_number);
94IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error); 97ToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error);
95bool i_toxav_audio_bitrate_invalid(uint32_t bitrate); 98bool i_toxav_audio_bitrate_invalid(uint32_t bitrate);
96bool i_toxav_video_bitrate_invalid(uint32_t bitrate); 99bool i_toxav_video_bitrate_invalid(uint32_t bitrate);
97bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call); 100bool i_toxav_prepare_transmission(ToxAV* av, ToxAVCall* call);
98void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number); 101void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number);
99 102
100 103
@@ -179,15 +182,13 @@ uint32_t toxav_iteration_interval(const ToxAV* av)
179 182
180void toxav_iteration(ToxAV* av) 183void toxav_iteration(ToxAV* av)
181{ 184{
182 msi_do(av->msi);
183
184 if (av->calls == NULL) 185 if (av->calls == NULL)
185 return; 186 return;
186 187
187 uint64_t start = current_time_monotonic(); 188 uint64_t start = current_time_monotonic();
188 uint32_t rc = 200 + av->dmssa; /* If no call is active interval is 200 */ 189 uint32_t rc = 200 + av->dmssa; /* If no call is active interval is 200 */
189 190
190 IToxAVCall* i = av->calls[av->calls_head]; 191 ToxAVCall* i = av->calls[av->calls_head];
191 for (; i; i = i->next) { 192 for (; i; i = i->next) {
192 if (i->active) { 193 if (i->active) {
193 cs_do(i->cs); 194 cs_do(i->cs);
@@ -207,22 +208,22 @@ void toxav_iteration(ToxAV* av)
207 208
208bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error) 209bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error)
209{ 210{
210 IToxAVCall* call = i_toxav_init_call(av, friend_number, error); 211 ToxAVCall* call = i_toxav_init_call(av, friend_number, error);
211 if (call == NULL) { 212 if (call == NULL)
212 return false; 213 return false;
213 }
214 214
215 /* TODO remove csettings */ 215 call->s_audio_b = audio_bit_rate;
216 MSICSettings csets; 216 call->s_video_b = video_bit_rate;
217 csets.audio_bitrate = audio_bit_rate;
218 csets.video_bitrate = video_bit_rate;
219 217
220 csets.call_type = video_bit_rate ? msi_TypeVideo : msi_TypeAudio; 218 uint8_t capabilities = 0;
221 219
222 if (msi_invite(av->msi, &call->call_idx, &csets, 1000, friend_number) != 0) { 220 capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0;
221 capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0;
222
223 if (msi_invite(av->msi, &call->msi_call, friend_number, capabilities) != 0) {
223 i_toxav_remove_call(av, friend_number); 224 i_toxav_remove_call(av, friend_number);
224 if (error) 225 if (error)
225 *error = TOXAV_ERR_CALL_MALLOC; /* FIXME: this should be the only reason to fail */ 226 *error = TOXAV_ERR_CALL_MALLOC;
226 return false; 227 return false;
227 } 228 }
228 229
@@ -250,23 +251,23 @@ bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, ui
250 goto END; 251 goto END;
251 } 252 }
252 253
253 IToxAVCall* call = i_toxav_get_call(av, friend_number); 254 ToxAVCall* call = i_toxav_get_call(av, friend_number);
254 if (call == NULL || av->msi->calls[call->call_idx]->state != msi_CallRequested) { 255 if (call == NULL) {
255 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING; 256 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING;
256 goto END; 257 goto END;
257 } 258 }
258 259
259 /* TODO remove csettings */ 260 call->s_audio_b = audio_bit_rate;
260 MSICSettings csets; 261 call->s_video_b = video_bit_rate;
261 csets.audio_bitrate = audio_bit_rate;
262 csets.video_bitrate = video_bit_rate;
263 262
264 csets.call_type = video_bit_rate ? msi_TypeVideo : msi_TypeAudio; 263 uint8_t capabilities = 0;
264
265 capabilities |= audio_bit_rate > 0 ? msi_CapSAudio : 0;
266 capabilities |= video_bit_rate > 0 ? msi_CapSVideo : 0;
267
268 if (msi_answer(call->msi_call, capabilities) != 0)
269 rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING; /* the only reason for msi_answer to fail */
265 270
266 if (msi_answer(av->msi, call->call_idx, &csets) != 0) {
267 rc = TOXAV_ERR_ANSWER_MALLOC; /* TODO Some error here */
268 /* TODO Reject call? */
269 }
270 271
271END: 272END:
272 if (error) 273 if (error)
@@ -291,7 +292,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
291 } 292 }
292 293
293 294
294 IToxAVCall* call = i_toxav_get_call(av, friend_number); 295 ToxAVCall* call = i_toxav_get_call(av, friend_number);
295 if (call == NULL) { 296 if (call == NULL) {
296 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; 297 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
297 goto END; 298 goto END;
@@ -309,17 +310,17 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
309 } break; 310 } break;
310 311
311 case TOXAV_CALL_CONTROL_CANCEL: { 312 case TOXAV_CALL_CONTROL_CANCEL: {
312 if (av->msi->calls[call->call_idx]->state == msi_CallActive) { 313 if (call->msi_call->state == msi_CallActive
314 || call->msi_call->state == msi_CallRequesting) {
313 /* Hang up */ 315 /* Hang up */
314 msi_hangup(av->msi, call->call_idx); 316 msi_hangup(call->msi_call);
315 } else if (av->msi->calls[call->call_idx]->state == msi_CallRequested) { 317 } else if (call->msi_call->state == msi_CallRequested) {
316 /* Reject the call */ 318 /* Reject the call */
317 msi_reject(av->msi, call->call_idx, NULL); 319 msi_reject(call->msi_call);
318 } else if (av->msi->calls[call->call_idx]->state == msi_CallRequesting) {
319 /* Cancel the call */
320 msi_cancel(av->msi, call->call_idx, 0, NULL);
321 i_toxav_remove_call(av, friend_number);
322 } 320 }
321
322 // No mather the case, terminate the call
323 i_toxav_remove_call(av, friend_number);
323 } break; 324 } break;
324 325
325 case TOXAV_CALL_CONTROL_MUTE_AUDIO: { 326 case TOXAV_CALL_CONTROL_MUTE_AUDIO: {
@@ -356,7 +357,7 @@ void toxav_callback_request_video_frame(ToxAV* av, toxav_request_video_frame_cb*
356bool 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) 357bool 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)
357{ 358{
358 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; 359 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
359 IToxAVCall* call; 360 ToxAVCall* call;
360 361
361 if (m_friend_exists(av->m, friend_number) == 0) { 362 if (m_friend_exists(av->m, friend_number) == 0) {
362 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND; 363 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
@@ -369,7 +370,7 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
369 goto END; 370 goto END;
370 } 371 }
371 372
372 if (av->msi->calls[call->call_idx]->state != msi_CallActive) { 373 if (call->msi_call->state != msi_CallActive) {
373 /* TODO */ 374 /* TODO */
374 rc = TOXAV_ERR_SEND_FRAME_NOT_REQUESTED; 375 rc = TOXAV_ERR_SEND_FRAME_NOT_REQUESTED;
375 goto END; 376 goto END;
@@ -453,7 +454,7 @@ void toxav_callback_request_audio_frame(ToxAV* av, toxav_request_audio_frame_cb*
453bool 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) 454bool 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)
454{ 455{
455 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; 456 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
456 IToxAVCall* call; 457 ToxAVCall* call;
457 458
458 if (m_friend_exists(av->m, friend_number) == 0) { 459 if (m_friend_exists(av->m, friend_number) == 0) {
459 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND; 460 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
@@ -466,7 +467,7 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
466 goto END; 467 goto END;
467 } 468 }
468 469
469 if (av->msi->calls[call->call_idx]->state != msi_CallActive) { 470 if (call->msi_call->state != msi_CallActive) {
470 /* TODO */ 471 /* TODO */
471 rc = TOXAV_ERR_SEND_FRAME_NOT_REQUESTED; 472 rc = TOXAV_ERR_SEND_FRAME_NOT_REQUESTED;
472 goto END; 473 goto END;
@@ -533,10 +534,10 @@ void i_callback_invite(void* toxav_inst, MSICall* call)
533{ 534{
534 ToxAV* toxav = toxav_inst; 535 ToxAV* toxav = toxav_inst;
535 536
536 IToxAVCall* av_call = i_toxav_init_call(toxav, call->friend_id, NULL); 537 ToxAVCall* av_call = i_toxav_init_call(toxav, call->friend_id, NULL);
537 if (av_call == NULL) { 538 if (av_call == NULL) {
538 LOGGER_WARNING("Failed to start call, rejecting..."); 539 LOGGER_WARNING("Failed to start call, rejecting...");
539 msi_reject(toxav->msi, call); 540 msi_reject(call);
540 return; 541 return;
541 } 542 }
542 543
@@ -559,15 +560,15 @@ void i_callback_start(void* toxav_inst, MSICall* call)
559{ 560{
560 ToxAV* toxav = toxav_inst; 561 ToxAV* toxav = toxav_inst;
561 562
562 IToxAVCall* call = i_toxav_get_call(toxav, call->friend_id); 563 ToxAVCall* av_call = i_toxav_get_call(toxav, call->friend_id);
563 564
564 if (call == NULL || !i_toxav_prepare_transmission(toxav, call)) { 565 if (av_call == NULL || !i_toxav_prepare_transmission(toxav, av_call)) {
565 /* TODO send error */ 566 /* TODO send error */
566 i_toxav_remove_call(toxav, call->friend_id); 567 i_toxav_remove_call(toxav, call->friend_id);
567 return; 568 return;
568 } 569 }
569 570
570 TOXAV_CALL_STATE state = capabilities_to_state(call->msi_call->peer_capabilities); 571 TOXAV_CALL_STATE state = capabilities_to_state(av_call->msi_call->peer_capabilities);
571 572
572 if (toxav->scb.first) 573 if (toxav->scb.first)
573 toxav->scb.first(toxav, call->friend_id, state, toxav->scb.second); 574 toxav->scb.first(toxav, call->friend_id, state, toxav->scb.second);
@@ -594,7 +595,7 @@ void i_callback_error(void* toxav_inst, MSICall* call)
594void i_callback_capabilites(void* toxav_inst, MSICall* call) 595void i_callback_capabilites(void* toxav_inst, MSICall* call)
595{ 596{
596 ToxAV* toxav = toxav_inst; 597 ToxAV* toxav = toxav_inst;
597 /* TODO something something msi */ 598 /* TODO handle this */
598} 599}
599 600
600TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities) 601TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities)
@@ -609,7 +610,7 @@ TOXAV_CALL_STATE capabilities_to_state(uint8_t capabilities)
609 return TOXAV_CALL_STATE_PAUSED; 610 return TOXAV_CALL_STATE_PAUSED;
610} 611}
611 612
612IToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number) 613ToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number)
613{ 614{
614 if (av->calls == NULL || av->calls_tail < friend_number) 615 if (av->calls == NULL || av->calls_tail < friend_number)
615 return NULL; 616 return NULL;
@@ -617,9 +618,9 @@ IToxAVCall* i_toxav_get_call(ToxAV* av, uint32_t friend_number)
617 return av->calls[friend_number]; 618 return av->calls[friend_number];
618} 619}
619 620
620IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number) 621ToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
621{ 622{
622 IToxAVCall* rc = calloc(sizeof(IToxAVCall), 1); 623 ToxAVCall* rc = calloc(sizeof(ToxAVCall), 1);
623 624
624 if (rc == NULL) 625 if (rc == NULL)
625 return NULL; 626 return NULL;
@@ -639,7 +640,7 @@ IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
639 640
640 641
641 if (av->calls == NULL) { /* Creating */ 642 if (av->calls == NULL) { /* Creating */
642 av->calls = calloc (sizeof(IToxAVCall*), friend_number + 1); 643 av->calls = calloc (sizeof(ToxAVCall*), friend_number + 1);
643 644
644 if (av->calls == NULL) { 645 if (av->calls == NULL) {
645 pthread_mutex_destroy(rc->mutex_control); 646 pthread_mutex_destroy(rc->mutex_control);
@@ -651,7 +652,7 @@ IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
651 av->calls_tail = av->calls_head = friend_number; 652 av->calls_tail = av->calls_head = friend_number;
652 653
653 } else if (av->calls_tail < friend_number) { /* Appending */ 654 } else if (av->calls_tail < friend_number) { /* Appending */
654 void* tmp = realloc(av->calls, sizeof(IToxAVCall*) * friend_number + 1); 655 void* tmp = realloc(av->calls, sizeof(ToxAVCall*) * friend_number + 1);
655 656
656 if (tmp == NULL) { 657 if (tmp == NULL) {
657 pthread_mutex_destroy(rc->mutex_control); 658 pthread_mutex_destroy(rc->mutex_control);
@@ -684,13 +685,13 @@ IToxAVCall* i_toxav_add_call(ToxAV* av, uint32_t friend_number)
684 685
685void i_toxav_remove_call(ToxAV* av, uint32_t friend_number) 686void i_toxav_remove_call(ToxAV* av, uint32_t friend_number)
686{ 687{
687 IToxAVCall* tc = i_toxav_get_call(av, friend_number); 688 ToxAVCall* tc = i_toxav_get_call(av, friend_number);
688 689
689 if (tc == NULL) 690 if (tc == NULL)
690 return; 691 return;
691 692
692 IToxAVCall* prev = tc->prev; 693 ToxAVCall* prev = tc->prev;
693 IToxAVCall* next = tc->next; 694 ToxAVCall* next = tc->next;
694 695
695 pthread_mutex_destroy(tc->mutex_control); 696 pthread_mutex_destroy(tc->mutex_control);
696 pthread_mutex_destroy(tc->mutex_do); 697 pthread_mutex_destroy(tc->mutex_do);
@@ -718,10 +719,10 @@ CLEAR:
718 av->calls = NULL; 719 av->calls = NULL;
719} 720}
720 721
721IToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error) 722ToxAVCall* i_toxav_init_call(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error)
722{ 723{
723 TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK; 724 TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK;
724 IToxAVCall* call = NULL; 725 ToxAVCall* call = NULL;
725 726
726 if (m_friend_exists(av->m, friend_number) == 0) { 727 if (m_friend_exists(av->m, friend_number) == 0) {
727 rc = TOXAV_ERR_CALL_FRIEND_NOT_FOUND; 728 rc = TOXAV_ERR_CALL_FRIEND_NOT_FOUND;
@@ -764,8 +765,12 @@ bool i_toxav_video_bitrate_invalid(uint32_t bitrate)
764 return false; 765 return false;
765} 766}
766 767
767bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call) 768bool i_toxav_prepare_transmission(ToxAV* av, ToxAVCall* call)
768{ 769{
770 if (!av->acb.first && !av->vcb.first)
771 /* It makes no sense to have CSession without callbacks */
772 return false;
773
769 pthread_mutex_lock(call->mutex_control); 774 pthread_mutex_lock(call->mutex_control);
770 775
771 if (call->active) { 776 if (call->active) {
@@ -788,11 +793,9 @@ bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call)
788 goto MUTEX_INIT_ERROR; 793 goto MUTEX_INIT_ERROR;
789 } 794 }
790 795
791 const MSICSettings *c_peer = &av->msi->calls[call->call_idx]->csettings_peer[0]; 796 uint8_t capabilities = call->msi_call->self_capabilities;
792 const MSICSettings *c_self = &av->msi->calls[call->call_idx]->csettings_local;
793 797
794 call->cs = cs_new(c_self->audio_bitrate, c_peer->audio_bitrate, 798 call->cs = cs_new(call->msi_call->peer_vfpsz);
795 c_self->video_bitrate, c_peer->video_bitrate);
796 799
797 if ( !call->cs ) { 800 if ( !call->cs ) {
798 LOGGER_ERROR("Error while starting Codec State!\n"); 801 LOGGER_ERROR("Error while starting Codec State!\n");
@@ -800,19 +803,14 @@ bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call)
800 } 803 }
801 804
802 call->cs->agent = av; 805 call->cs->agent = av;
803 806 call->cs->friend_id = call->friend_id;
804 /* It makes no sense to have CSession without callbacks */
805 assert(av->acb.first || av->vcb.first);
806 807
807 memcpy(&call->cs->acb, &av->acb, sizeof(av->acb)); 808 memcpy(&call->cs->acb, &av->acb, sizeof(av->acb));
808 memcpy(&call->cs->vcb, &av->vcb, sizeof(av->vcb)); 809 memcpy(&call->cs->vcb, &av->vcb, sizeof(av->vcb));
809 810
810 call->cs->friend_number = call->friend_id; 811 if (capabilities & msi_CapSAudio || capabilities & msi_CapRAudio) { /* Prepare audio sending */
811 call->cs->call_idx = call->call_idx; 812
812 813 call->rtps[audio_index] = rtp_new(rtp_TypeAudio, av->m, call->friend_id);
813
814 if (c_self->audio_bitrate > 0 || c_peer->audio_bitrate > 0) { /* Prepare audio rtp */
815 call->rtps[audio_index] = rtp_new(rtp_TypeAudio, av->m, av->msi->calls[call->call_idx]->peers[0]);
816 814
817 if ( !call->rtps[audio_index] ) { 815 if ( !call->rtps[audio_index] ) {
818 LOGGER_ERROR("Error while starting audio RTP session!\n"); 816 LOGGER_ERROR("Error while starting audio RTP session!\n");
@@ -821,12 +819,23 @@ bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call)
821 819
822 call->rtps[audio_index]->cs = call->cs; 820 call->rtps[audio_index]->cs = call->cs;
823 821
824 if (c_peer->audio_bitrate > 0) 822 if (cs_enable_audio_sending(call->cs, call->s_audio_b, 2) != 0) {
823 LOGGER_WARNING("Failed to enable audio sending!");
824 goto FAILURE;
825 }
826
827 if (capabilities & msi_CapRAudio) {
828 if (cs_enable_audio_receiving(call->cs) != 0) {
829 LOGGER_WARNING("Failed to enable audio receiving!");
830 goto FAILURE;
831 }
832
825 rtp_register_for_receiving(call->rtps[audio_index]); 833 rtp_register_for_receiving(call->rtps[audio_index]);
834 }
826 } 835 }
827 836
828 if (c_self->video_bitrate > 0 || c_peer->video_bitrate > 0) { /* Prepare video rtp */ 837 if (capabilities & msi_CapSVideo || capabilities & msi_CapRVideo) { /* Prepare video rtp */
829 call->rtps[video_index] = rtp_new(rtp_TypeVideo, av->m, av->msi->calls[call->call_idx]->peers[0]); 838 call->rtps[video_index] = rtp_new(rtp_TypeVideo, av->m, call->friend_id);
830 839
831 if ( !call->rtps[video_index] ) { 840 if ( !call->rtps[video_index] ) {
832 LOGGER_ERROR("Error while starting video RTP session!\n"); 841 LOGGER_ERROR("Error while starting video RTP session!\n");
@@ -835,8 +844,19 @@ bool i_toxav_prepare_transmission(ToxAV* av, IToxAVCall* call)
835 844
836 call->rtps[video_index]->cs = call->cs; 845 call->rtps[video_index]->cs = call->cs;
837 846
838 if (c_peer->video_bitrate > 0) 847 if (cs_enable_video_sending(call->cs, call->s_video_b) != 0) {
848 LOGGER_WARNING("Failed to enable video sending!");
849 goto FAILURE;
850 }
851
852 if (capabilities & msi_CapRVideo) {
853 if (cs_enable_video_receiving(call->cs) != 0) {
854 LOGGER_WARNING("Failed to enable video receiving!");
855 goto FAILURE;
856 }
857
839 rtp_register_for_receiving(call->rtps[audio_index]); 858 rtp_register_for_receiving(call->rtps[audio_index]);
859 }
840 } 860 }
841 861
842 call->active = 1; 862 call->active = 1;
@@ -866,7 +886,7 @@ MUTEX_INIT_ERROR:
866 886
867void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number) 887void i_toxav_kill_transmission(ToxAV* av, uint32_t friend_number)
868{ 888{
869 IToxAVCall* call = i_toxav_get_call(av, friend_number); 889 ToxAVCall* call = i_toxav_get_call(av, friend_number);
870 if (!call) 890 if (!call)
871 return; 891 return;
872 892
diff --git a/toxav/toxav_new_1.c b/toxav/toxav_new_1.c
index ee7f49a6..145dcf48 100644
--- a/toxav/toxav_new_1.c
+++ b/toxav/toxav_new_1.c
@@ -317,7 +317,6 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, int support_vide
317 } 317 }
318 318
319 call->cs->agent = av; 319 call->cs->agent = av;
320 call->cs->call_idx = call_index;
321 320
322 call->cs->acb.first = av->acb.first; 321 call->cs->acb.first = av->acb.first;
323 call->cs->acb.second = av->acb.second; 322 call->cs->acb.second = av->acb.second;