diff options
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/av_test.c | 61 | ||||
-rw-r--r-- | toxav/codec.c | 10 | ||||
-rw-r--r-- | toxav/rtp.c | 7 | ||||
-rw-r--r-- | toxav/toxav.c | 33 | ||||
-rw-r--r-- | toxav/toxav.h | 6 |
5 files changed, 91 insertions, 26 deletions
diff --git a/toxav/av_test.c b/toxav/av_test.c index 01484249..46fd97e1 100644 --- a/toxav/av_test.c +++ b/toxav/av_test.c | |||
@@ -39,6 +39,7 @@ | |||
39 | typedef struct { | 39 | typedef struct { |
40 | bool incoming; | 40 | bool incoming; |
41 | uint32_t state; | 41 | uint32_t state; |
42 | uint32_t output_source; | ||
42 | } CallControl; | 43 | } CallControl; |
43 | 44 | ||
44 | const char* stringify_state(TOXAV_CALL_STATE s) | 45 | const char* stringify_state(TOXAV_CALL_STATE s) |
@@ -58,6 +59,8 @@ const char* stringify_state(TOXAV_CALL_STATE s) | |||
58 | }; | 59 | }; |
59 | 60 | ||
60 | 61 | ||
62 | int device_play_frame(uint32_t source, const int16_t* PCM, size_t size); | ||
63 | |||
61 | /** | 64 | /** |
62 | * Callbacks | 65 | * Callbacks |
63 | */ | 66 | */ |
@@ -86,7 +89,7 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, | |||
86 | uint32_t sampling_rate, | 89 | uint32_t sampling_rate, |
87 | void *user_data) | 90 | void *user_data) |
88 | { | 91 | { |
89 | printf("Handling AUDIO FRAME callback\n"); | 92 | device_play_frame(((CallControl*)user_data)->output_source, pcm, sample_count); |
90 | } | 93 | } |
91 | void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) | 94 | void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) |
92 | { | 95 | { |
@@ -173,7 +176,7 @@ int device_read_frame(ALCdevice* device, int32_t frame_dur, int16_t* PCM, size_t | |||
173 | return f_size; | 176 | return f_size; |
174 | } | 177 | } |
175 | 178 | ||
176 | int device_play_frame(uint32_t source, int16_t* PCM, size_t size) | 179 | int device_play_frame(uint32_t source, const int16_t* PCM, size_t size) |
177 | { | 180 | { |
178 | uint32_t bufid; | 181 | uint32_t bufid; |
179 | int32_t processed, queued; | 182 | int32_t processed, queued; |
@@ -604,17 +607,67 @@ int main (int argc, char** argv) | |||
604 | if (TEST_TRANSFER_A) { /* Audio encoding/decoding and transfer */ | 607 | if (TEST_TRANSFER_A) { /* Audio encoding/decoding and transfer */ |
605 | printf("\nTrying audio enc/dec...\n"); | 608 | printf("\nTrying audio enc/dec...\n"); |
606 | 609 | ||
610 | memset(&AliceCC, 0, sizeof(CallControl)); | ||
611 | memset(&BobCC, 0, sizeof(CallControl)); | ||
612 | |||
613 | AliceCC.output_source = BobCC.output_source = source; | ||
614 | |||
615 | { | ||
616 | TOXAV_ERR_CALL rc; | ||
617 | toxav_call(AliceAV, 0, 48, 0, &rc); | ||
618 | |||
619 | if (rc != TOXAV_ERR_CALL_OK) { | ||
620 | printf("toxav_call failed: %d\n", rc); | ||
621 | exit(1); | ||
622 | } | ||
623 | } | ||
624 | |||
625 | while (!BobCC.incoming) | ||
626 | iterate(Bsn, AliceAV, BobAV); | ||
627 | |||
628 | { | ||
629 | TOXAV_ERR_ANSWER rc; | ||
630 | toxav_answer(BobAV, 0, 48, 0, &rc); | ||
631 | |||
632 | if (rc != TOXAV_ERR_ANSWER_OK) { | ||
633 | printf("toxav_answer failed: %d\n", rc); | ||
634 | exit(1); | ||
635 | } | ||
636 | } | ||
637 | |||
638 | iterate(Bsn, AliceAV, BobAV); | ||
639 | |||
607 | int16_t PCM[10000]; | 640 | int16_t PCM[10000]; |
608 | time_t start_time = time(NULL); | 641 | time_t start_time = time(NULL); |
609 | 642 | ||
610 | /* Run for 5 seconds */ | 643 | /* Run for 5 seconds */ |
611 | while ( start_time + 10 > time(NULL) ) { | 644 | while ( start_time + 10 > time(NULL) ) { |
612 | int frame_size = device_read_frame(in_device, 20, PCM, sizeof(PCM)); | 645 | int frame_size = device_read_frame(in_device, 20, PCM, sizeof(PCM)); |
613 | if (frame_size > 0) | 646 | if (frame_size > 0) { |
614 | device_play_frame(source, PCM, frame_size); | 647 | TOXAV_ERR_SEND_FRAME rc; |
648 | if (toxav_send_audio_frame(AliceAV, 0, PCM, frame_size, 2, 48000, &rc) == false) { | ||
649 | printf("Error sending frame of size %d: %d\n", frame_size, rc); | ||
650 | exit (1); | ||
651 | } | ||
652 | } | ||
653 | |||
654 | iterate(Bsn, AliceAV, BobAV); | ||
615 | // c_sleep(20); | 655 | // c_sleep(20); |
616 | } | 656 | } |
617 | 657 | ||
658 | { | ||
659 | TOXAV_ERR_CALL_CONTROL rc; | ||
660 | toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); | ||
661 | |||
662 | if (rc != TOXAV_ERR_CALL_CONTROL_OK) { | ||
663 | printf("toxav_call_control failed: %d\n", rc); | ||
664 | exit(1); | ||
665 | } | ||
666 | } | ||
667 | |||
668 | iterate(Bsn, AliceAV, BobAV); | ||
669 | assert(BobCC.state == TOXAV_CALL_STATE_END); | ||
670 | |||
618 | printf("Success!"); | 671 | printf("Success!"); |
619 | } | 672 | } |
620 | 673 | ||
diff --git a/toxav/codec.c b/toxav/codec.c index bf94115e..80975b70 100644 --- a/toxav/codec.c +++ b/toxav/codec.c | |||
@@ -245,7 +245,7 @@ void cs_do(CSSession *cs) | |||
245 | /* Codec session should always be protected by call mutex so no need to check for cs validity | 245 | /* Codec session should always be protected by call mutex so no need to check for cs validity |
246 | */ | 246 | */ |
247 | 247 | ||
248 | if (!cs) | 248 | if (!cs) |
249 | return; | 249 | return; |
250 | 250 | ||
251 | Payload *p; | 251 | Payload *p; |
@@ -258,7 +258,7 @@ void cs_do(CSSession *cs) | |||
258 | if (cs->audio_decoder) { /* If receiving enabled */ | 258 | if (cs->audio_decoder) { /* If receiving enabled */ |
259 | RTPMessage *msg; | 259 | RTPMessage *msg; |
260 | 260 | ||
261 | uint16_t fsize = 5760; /* Max frame size for 48 kHz */ | 261 | uint16_t fsize = 16000; /* Max frame size for 48 kHz */ |
262 | int16_t tmp[fsize * 2]; | 262 | int16_t tmp[fsize * 2]; |
263 | 263 | ||
264 | while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) { | 264 | while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) { |
@@ -284,6 +284,7 @@ void cs_do(CSSession *cs) | |||
284 | continue; | 284 | continue; |
285 | } | 285 | } |
286 | 286 | ||
287 | LOGGER_DEBUG("Decoding packet of length: %d", msg->length); | ||
287 | rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, fsize, 0); | 288 | rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, fsize, 0); |
288 | rtp_free_msg(NULL, msg); | 289 | rtp_free_msg(NULL, msg); |
289 | } | 290 | } |
@@ -741,8 +742,9 @@ void queue_message(RTPSession *session, RTPMessage *msg) | |||
741 | */ | 742 | */ |
742 | CSSession *cs = session->cs; | 743 | CSSession *cs = session->cs; |
743 | 744 | ||
744 | if (!cs) return; | 745 | if (!cs) |
745 | 746 | return; | |
747 | |||
746 | /* Audio */ | 748 | /* Audio */ |
747 | if (session->payload_type == rtp_TypeAudio % 128) { | 749 | if (session->payload_type == rtp_TypeAudio % 128) { |
748 | pthread_mutex_lock(cs->queue_mutex); | 750 | pthread_mutex_lock(cs->queue_mutex); |
diff --git a/toxav/rtp.c b/toxav/rtp.c index 8319c7dc..e5f45310 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c | |||
@@ -363,7 +363,6 @@ int rtp_handle_packet ( Messenger *m, int32_t friendnumber, const uint8_t *data, | |||
363 | } | 363 | } |
364 | 364 | ||
365 | queue_message(session, msg); | 365 | queue_message(session, msg); |
366 | |||
367 | return 0; | 366 | return 0; |
368 | } | 367 | } |
369 | 368 | ||
@@ -427,8 +426,6 @@ RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num ) | |||
427 | return NULL; | 426 | return NULL; |
428 | } | 427 | } |
429 | 428 | ||
430 | LOGGER_DEBUG("Registered packet handler: pt: %d; fid: %d", payload_type, friend_num); | ||
431 | |||
432 | retu->version = RTP_VERSION; /* It's always 2 */ | 429 | retu->version = RTP_VERSION; /* It's always 2 */ |
433 | retu->padding = 0; /* If some additional data is needed about the packet */ | 430 | retu->padding = 0; /* If some additional data is needed about the packet */ |
434 | retu->extension = 0; /* If extension to header is needed */ | 431 | retu->extension = 0; /* If extension to header is needed */ |
@@ -467,7 +464,7 @@ void rtp_kill ( RTPSession *session ) | |||
467 | { | 464 | { |
468 | if ( !session ) return; | 465 | if ( !session ) return; |
469 | 466 | ||
470 | custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, NULL, NULL); | 467 | rtp_stop_receiving (session); |
471 | 468 | ||
472 | free ( session->ext_header ); | 469 | free ( session->ext_header ); |
473 | free ( session->csrc ); | 470 | free ( session->csrc ); |
@@ -483,6 +480,7 @@ int rtp_start_receiving(RTPSession* session) | |||
483 | if (session == NULL) | 480 | if (session == NULL) |
484 | return 0; | 481 | return 0; |
485 | 482 | ||
483 | LOGGER_DEBUG("Registering packet handler: pt: %d; friend: %d", session->prefix, session->dest); | ||
486 | return custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, | 484 | return custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, |
487 | rtp_handle_packet, session); | 485 | rtp_handle_packet, session); |
488 | } | 486 | } |
@@ -492,6 +490,7 @@ int rtp_stop_receiving(RTPSession* session) | |||
492 | if (session == NULL) | 490 | if (session == NULL) |
493 | return 0; | 491 | return 0; |
494 | 492 | ||
493 | LOGGER_DEBUG("Unregistering packet handler: pt: %d; friend: %d", session->prefix, session->dest); | ||
495 | return custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, | 494 | return custom_lossy_packet_registerhandler(session->m, session->dest, session->prefix, |
496 | NULL, NULL); | 495 | NULL, NULL); |
497 | } | 496 | } |
diff --git a/toxav/toxav.c b/toxav/toxav.c index 78243ae6..7cf8cec4 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -215,13 +215,6 @@ void toxav_iteration(ToxAV* av) | |||
215 | for (; i; i = i->next) { | 215 | for (; i; i = i->next) { |
216 | if (i->active) { | 216 | if (i->active) { |
217 | pthread_mutex_lock(i->mutex_decoding); | 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); | 218 | pthread_mutex_unlock(av->mutex); |
226 | cs_do(i->cs); | 219 | cs_do(i->cs); |
227 | rc = MIN(i->cs->last_packet_frame_duration, rc); | 220 | rc = MIN(i->cs->last_packet_frame_duration, rc); |
@@ -304,6 +297,11 @@ bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, ui | |||
304 | goto END; | 297 | goto END; |
305 | } | 298 | } |
306 | 299 | ||
300 | if (!call_prepare_transmission(call)) { | ||
301 | rc = TOXAV_ERR_ANSWER_MALLOC; | ||
302 | goto END; | ||
303 | } | ||
304 | |||
307 | call->s_audio_b = audio_bit_rate; | 305 | call->s_audio_b = audio_bit_rate; |
308 | call->s_video_b = video_bit_rate; | 306 | call->s_video_b = video_bit_rate; |
309 | 307 | ||
@@ -645,7 +643,7 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc | |||
645 | goto END; | 643 | goto END; |
646 | } | 644 | } |
647 | 645 | ||
648 | if ( channels != 1 || channels != 2 ) { | 646 | if ( channels != 1 && channels != 2 ) { |
649 | pthread_mutex_unlock(call->mutex_audio_sending); | 647 | pthread_mutex_unlock(call->mutex_audio_sending); |
650 | rc = TOXAV_ERR_SEND_FRAME_INVALID; | 648 | rc = TOXAV_ERR_SEND_FRAME_INVALID; |
651 | goto END; | 649 | goto END; |
@@ -666,8 +664,12 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc | |||
666 | goto END; | 664 | goto END; |
667 | } | 665 | } |
668 | 666 | ||
669 | vrc = rtp_send_msg(call->rtps[audio_index], dest, vrc); | 667 | if (rtp_send_msg(call->rtps[audio_index], dest, vrc) != 0) { |
670 | /* TODO check for error? */ | 668 | LOGGER_WARNING("Failed to send audio packet"); |
669 | rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED; | ||
670 | } | ||
671 | |||
672 | LOGGER_DEBUG("Sent packet of size: %d (o %d)", vrc, sample_count); | ||
671 | } | 673 | } |
672 | 674 | ||
673 | pthread_mutex_unlock(call->mutex_audio_sending); | 675 | pthread_mutex_unlock(call->mutex_audio_sending); |
@@ -965,7 +967,10 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
965 | goto FAILURE; | 967 | goto FAILURE; |
966 | } | 968 | } |
967 | 969 | ||
968 | rtp_start_receiving(call->rtps[audio_index]); | 970 | if (rtp_start_receiving(call->rtps[audio_index]) != 0) { |
971 | LOGGER_WARNING("Failed to enable audio receiving!"); | ||
972 | goto FAILURE; | ||
973 | } | ||
969 | } | 974 | } |
970 | 975 | ||
971 | { /* Prepare video */ | 976 | { /* Prepare video */ |
@@ -984,13 +989,15 @@ bool call_prepare_transmission(ToxAVCall* call) | |||
984 | goto FAILURE; | 989 | goto FAILURE; |
985 | } | 990 | } |
986 | 991 | ||
987 | |||
988 | if (cs_enable_video_receiving(call->cs) != 0) { | 992 | if (cs_enable_video_receiving(call->cs) != 0) { |
989 | LOGGER_WARNING("Failed to enable video receiving!"); | 993 | LOGGER_WARNING("Failed to enable video receiving!"); |
990 | goto FAILURE; | 994 | goto FAILURE; |
991 | } | 995 | } |
992 | 996 | ||
993 | rtp_start_receiving(call->rtps[audio_index]); | 997 | if (rtp_start_receiving(call->rtps[video_index]) != 0) { |
998 | LOGGER_WARNING("Failed to enable audio receiving!"); | ||
999 | goto FAILURE; | ||
1000 | } | ||
994 | } | 1001 | } |
995 | 1002 | ||
996 | call->active = 1; | 1003 | call->active = 1; |
diff --git a/toxav/toxav.h b/toxav/toxav.h index 101047ed..571282ed 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h | |||
@@ -380,7 +380,11 @@ typedef enum TOXAV_ERR_SEND_FRAME { | |||
380 | * One of the frame parameters was invalid. E.g. the resolution may be too | 380 | * One of the frame parameters was invalid. E.g. the resolution may be too |
381 | * small or too large, or the audio sampling rate may be unsupported. | 381 | * small or too large, or the audio sampling rate may be unsupported. |
382 | */ | 382 | */ |
383 | TOXAV_ERR_SEND_FRAME_INVALID | 383 | TOXAV_ERR_SEND_FRAME_INVALID, |
384 | /** | ||
385 | * Failed to push frame through rtp interface. | ||
386 | */ | ||
387 | TOXAV_ERR_SEND_FRAME_RTP_FAILED | ||
384 | } TOXAV_ERR_SEND_FRAME; | 388 | } TOXAV_ERR_SEND_FRAME; |
385 | /** | 389 | /** |
386 | * The function type for the `request_video_frame` callback. | 390 | * The function type for the `request_video_frame` callback. |