diff --git a/auto_tests/dht_test.c b/auto_tests/dht_test.c index 32985bca..8304a046 100644 --- a/auto_tests/dht_test.c +++ b/auto_tests/dht_test.c @@ -153,7 +153,8 @@ void test_addto_lists_bad(DHT *dht, { // check "bad" clients replacement int used, test1, test2, test3; - uint8_t public_key[crypto_box_PUBLICKEYBYTES], test_id1[crypto_box_PUBLICKEYBYTES], test_id2[crypto_box_PUBLICKEYBYTES], test_id3[crypto_box_PUBLICKEYBYTES]; + uint8_t public_key[crypto_box_PUBLICKEYBYTES], test_id1[crypto_box_PUBLICKEYBYTES], test_id2[crypto_box_PUBLICKEYBYTES], + test_id3[crypto_box_PUBLICKEYBYTES]; uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0; randombytes(public_key, sizeof(public_key)); @@ -196,7 +197,8 @@ void test_addto_lists_possible_bad(DHT *dht, { // check "possibly bad" clients replacement int used, test1, test2, test3; - uint8_t public_key[crypto_box_PUBLICKEYBYTES], test_id1[crypto_box_PUBLICKEYBYTES], test_id2[crypto_box_PUBLICKEYBYTES], test_id3[crypto_box_PUBLICKEYBYTES]; + uint8_t public_key[crypto_box_PUBLICKEYBYTES], test_id1[crypto_box_PUBLICKEYBYTES], test_id2[crypto_box_PUBLICKEYBYTES], + test_id3[crypto_box_PUBLICKEYBYTES]; uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0; randombytes(public_key, sizeof(public_key)); diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c index 5821a6d4..20432dca 100644 --- a/auto_tests/toxav_basic_test.c +++ b/auto_tests/toxav_basic_test.c @@ -49,12 +49,12 @@ typedef struct { bool incoming; uint32_t state; - + } CallControl; /** - * Callbacks + * Callbacks */ void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data) { @@ -62,17 +62,17 @@ void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool (void) friend_number; (void) audio_enabled; (void) video_enabled; - + printf("Handling CALL callback\n"); - ((CallControl*)user_data)->incoming = true; + ((CallControl *)user_data)->incoming = true; } void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data) { (void) av; (void) friend_number; - + printf("Handling CALL STATE callback: %d\n", state); - ((CallControl*)user_data)->state = state; + ((CallControl *)user_data)->state = state; } void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height, @@ -112,7 +112,7 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) { (void) userdata; - + if (length == 7 && memcmp("gentoo", data, 7) == 0) { ck_assert(tox_friend_add_norequest(m, public_key, NULL) != (uint32_t) ~0); } @@ -122,12 +122,12 @@ void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t /** * Iterate helper */ -int iterate_tox(Tox* bootstrap, Tox* Alice, Tox* Bob) +int iterate_tox(Tox *bootstrap, Tox *Alice, Tox *Bob) { tox_iterate(bootstrap); tox_iterate(Alice); tox_iterate(Bob); - + return MIN(tox_iteration_interval(Alice), tox_iteration_interval(Bob)); } @@ -135,80 +135,80 @@ int iterate_tox(Tox* bootstrap, Tox* Alice, Tox* Bob) START_TEST(test_AV_flows) { - Tox* Alice, *Bob, *bootstrap; - ToxAV* AliceAV, *BobAV; - + Tox *Alice, *Bob, *bootstrap; + ToxAV *AliceAV, *BobAV; + CallControl AliceCC, BobCC; - + { TOX_ERR_NEW error; - + bootstrap = tox_new(NULL, &error); ck_assert(error == TOX_ERR_NEW_OK); - + Alice = tox_new(NULL, &error); ck_assert(error == TOX_ERR_NEW_OK); - + Bob = tox_new(NULL, &error); ck_assert(error == TOX_ERR_NEW_OK); } - + printf("Created 3 instances of Tox\n"); printf("Preparing network...\n"); long long unsigned int cur_time = time(NULL); - + uint32_t to_compare = 974536; uint8_t address[TOX_ADDRESS_SIZE]; - + tox_callback_friend_request(Alice, t_accept_friend_request_cb, &to_compare); tox_self_get_address(Alice, address); - - + + ck_assert(tox_friend_add(Bob, address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0); - + uint8_t off = 1; - + while (1) { iterate_tox(bootstrap, Alice, Bob); - - if (tox_self_get_connection_status(bootstrap) && - tox_self_get_connection_status(Alice) && - tox_self_get_connection_status(Bob) && off) { + + if (tox_self_get_connection_status(bootstrap) && + tox_self_get_connection_status(Alice) && + tox_self_get_connection_status(Bob) && off) { printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); off = 0; } - - if (tox_friend_get_connection_status(Alice, 0, NULL) == TOX_CONNECTION_UDP && - tox_friend_get_connection_status(Bob, 0, NULL) == TOX_CONNECTION_UDP) + + if (tox_friend_get_connection_status(Alice, 0, NULL) == TOX_CONNECTION_UDP && + tox_friend_get_connection_status(Bob, 0, NULL) == TOX_CONNECTION_UDP) break; - + c_sleep(20); } - - + + { TOXAV_ERR_NEW error; AliceAV = toxav_new(Alice, &error); ck_assert(error == TOXAV_ERR_NEW_OK); - + BobAV = toxav_new(Bob, &error); ck_assert(error == TOXAV_ERR_NEW_OK); } - + toxav_callback_call(AliceAV, t_toxav_call_cb, &AliceCC); toxav_callback_call_state(AliceAV, t_toxav_call_state_cb, &AliceCC); toxav_callback_video_receive_frame(AliceAV, t_toxav_receive_video_frame_cb, &AliceCC); toxav_callback_audio_receive_frame(AliceAV, t_toxav_receive_audio_frame_cb, &AliceCC); - + toxav_callback_call(BobAV, t_toxav_call_cb, &BobCC); toxav_callback_call_state(BobAV, t_toxav_call_state_cb, &BobCC); toxav_callback_video_receive_frame(BobAV, t_toxav_receive_video_frame_cb, &BobCC); toxav_callback_audio_receive_frame(BobAV, t_toxav_receive_audio_frame_cb, &BobCC); - + printf("Created 2 instances of ToxAV\n"); printf("All set after %llu seconds!\n", time(NULL) - cur_time); - - + + #define REGULAR_CALL_FLOW(A_BR, V_BR) \ do { \ memset(&AliceCC, 0, sizeof(CallControl)); \ @@ -256,117 +256,117 @@ START_TEST(test_AV_flows) } \ printf("Success!\n");\ } while(0) - + if (TEST_REGULAR_AV) { printf("\nTrying regular call (Audio and Video)...\n"); REGULAR_CALL_FLOW(48, 4000); } - + if (TEST_REGULAR_A) { printf("\nTrying regular call (Audio only)...\n"); REGULAR_CALL_FLOW(48, 0); } - + if (TEST_REGULAR_V) { printf("\nTrying regular call (Video only)...\n"); REGULAR_CALL_FLOW(0, 4000); } - + #undef REGULAR_CALL_FLOW - + if (TEST_REJECT) { /* Alice calls; Bob rejects */ printf("\nTrying reject flow...\n"); - + memset(&AliceCC, 0, sizeof(CallControl)); memset(&BobCC, 0, sizeof(CallControl)); - + { TOXAV_ERR_CALL rc; toxav_call(AliceAV, 0, 48, 0, &rc); - + if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); ck_assert(0); } } - + while (!BobCC.incoming) iterate_tox(bootstrap, Alice, Bob); - + /* Reject */ { TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(BobAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); - + if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d\n", rc); ck_assert(0); } } - + while (AliceCC.state != TOXAV_FRIEND_CALL_STATE_FINISHED) iterate_tox(bootstrap, Alice, Bob); - + printf("Success!\n"); } - + if (TEST_CANCEL) { /* Alice calls; Alice cancels while ringing */ printf("\nTrying cancel (while ringing) flow...\n"); - + memset(&AliceCC, 0, sizeof(CallControl)); memset(&BobCC, 0, sizeof(CallControl)); - + { TOXAV_ERR_CALL rc; toxav_call(AliceAV, 0, 48, 0, &rc); - + if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); ck_assert(0); } } - + while (!BobCC.incoming) iterate_tox(bootstrap, Alice, Bob); - + /* Cancel */ { TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); - + if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d\n", rc); ck_assert(0); } } - + /* Alice will not receive end state */ while (BobCC.state != TOXAV_FRIEND_CALL_STATE_FINISHED) iterate_tox(bootstrap, Alice, Bob); - + printf("Success!\n"); } - + if (TEST_MUTE_UNMUTE) { /* Check Mute-Unmute etc */ printf("\nTrying mute functionality...\n"); - + memset(&AliceCC, 0, sizeof(CallControl)); memset(&BobCC, 0, sizeof(CallControl)); - + /* Assume sending audio and video */ { TOXAV_ERR_CALL rc; toxav_call(AliceAV, 0, 48, 1000, &rc); - + if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); ck_assert(0); } } - + while (!BobCC.incoming) iterate_tox(bootstrap, Alice, Bob); - + /* At first try all stuff while in invalid state */ ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL)); @@ -374,19 +374,19 @@ START_TEST(test_AV_flows) ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL)); ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_HIDE_VIDEO, NULL)); ck_assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_SHOW_VIDEO, NULL)); - + { TOXAV_ERR_ANSWER rc; toxav_answer(BobAV, 0, 48, 4000, &rc); - + if (rc != TOXAV_ERR_ANSWER_OK) { printf("toxav_answer failed: %d\n", rc); ck_assert(0); } } - + iterate_tox(bootstrap, Alice, Bob); - + /* Pause and Resume */ printf("Pause and Resume\n"); ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); @@ -395,7 +395,7 @@ START_TEST(test_AV_flows) ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL)); iterate_tox(bootstrap, Alice, Bob); ck_assert(BobCC.state & (TOXAV_FRIEND_CALL_STATE_SENDING_A | TOXAV_FRIEND_CALL_STATE_SENDING_V)); - + /* Mute/Unmute single */ printf("Mute/Unmute single\n"); ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL)); @@ -404,7 +404,7 @@ START_TEST(test_AV_flows) ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_UNMUTE_AUDIO, NULL)); iterate_tox(bootstrap, Alice, Bob); ck_assert(BobCC.state & TOXAV_FRIEND_CALL_STATE_ACCEPTING_A); - + /* Mute/Unmute both */ printf("Mute/Unmute both\n"); ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_MUTE_AUDIO, NULL)); @@ -419,122 +419,122 @@ START_TEST(test_AV_flows) ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_SHOW_VIDEO, NULL)); iterate_tox(bootstrap, Alice, Bob); ck_assert(BobCC.state & TOXAV_FRIEND_CALL_STATE_ACCEPTING_V); - + { TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); - + if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d\n", rc); ck_assert(0); } } - + iterate_tox(bootstrap, Alice, Bob); ck_assert(BobCC.state == TOXAV_FRIEND_CALL_STATE_FINISHED); - + printf("Success!\n"); } - + if (TEST_STOP_RESUME_PAYLOAD) { /* Stop and resume audio/video payload */ printf("\nTrying stop/resume functionality...\n"); - + memset(&AliceCC, 0, sizeof(CallControl)); memset(&BobCC, 0, sizeof(CallControl)); - + /* Assume sending audio and video */ { TOXAV_ERR_CALL rc; toxav_call(AliceAV, 0, 48, 0, &rc); - + if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); ck_assert(0); } } - + while (!BobCC.incoming) iterate_tox(bootstrap, Alice, Bob); - + { TOXAV_ERR_ANSWER rc; toxav_answer(BobAV, 0, 48, 0, &rc); - + if (rc != TOXAV_ERR_ANSWER_OK) { printf("toxav_answer failed: %d\n", rc); ck_assert(0); } } - + iterate_tox(bootstrap, Alice, Bob); - + printf("Call started as audio only\n"); printf("Turning on video for Alice...\n"); ck_assert(toxav_bit_rate_set(AliceAV, 0, -1, 1000, NULL)); - + iterate_tox(bootstrap, Alice, Bob); ck_assert(BobCC.state & TOXAV_FRIEND_CALL_STATE_SENDING_V); - + printf("Turning off video for Alice...\n"); ck_assert(toxav_bit_rate_set(AliceAV, 0, -1, 0, NULL)); - + iterate_tox(bootstrap, Alice, Bob); ck_assert(!(BobCC.state & TOXAV_FRIEND_CALL_STATE_SENDING_V)); - + printf("Turning off audio for Alice...\n"); ck_assert(toxav_bit_rate_set(AliceAV, 0, 0, -1, NULL)); - + iterate_tox(bootstrap, Alice, Bob); ck_assert(!(BobCC.state & TOXAV_FRIEND_CALL_STATE_SENDING_A)); - + { TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); - + if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d\n", rc); ck_assert(0); } } - + iterate_tox(bootstrap, Alice, Bob); ck_assert(BobCC.state == TOXAV_FRIEND_CALL_STATE_FINISHED); - + printf("Success!\n"); } - + if (TEST_PAUSE_RESUME_SEND) { /* Stop and resume audio/video payload and test send options */ printf("\nTrying stop/resume functionality...\n"); - + memset(&AliceCC, 0, sizeof(CallControl)); memset(&BobCC, 0, sizeof(CallControl)); - + /* Assume sending audio and video */ { TOXAV_ERR_CALL rc; toxav_call(AliceAV, 0, 48, 0, &rc); - + if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); ck_assert(0); } } - + while (!BobCC.incoming) iterate_tox(bootstrap, Alice, Bob); - + { TOXAV_ERR_ANSWER rc; toxav_answer(BobAV, 0, 48, 0, &rc); - + if (rc != TOXAV_ERR_ANSWER_OK) { printf("toxav_answer failed: %d\n", rc); ck_assert(0); } } - + int16_t PCM[5670]; - + iterate_tox(bootstrap, Alice, Bob); ck_assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); iterate_tox(bootstrap, Alice, Bob); @@ -545,29 +545,29 @@ START_TEST(test_AV_flows) ck_assert(toxav_audio_send_frame(AliceAV, 0, PCM, 960, 1, 48000, NULL)); ck_assert(toxav_audio_send_frame(BobAV, 0, PCM, 960, 1, 48000, NULL)); iterate_tox(bootstrap, Alice, Bob); - + { TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); - + if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d\n", rc); ck_assert(0); } } - + iterate_tox(bootstrap, Alice, Bob); ck_assert(BobCC.state == TOXAV_FRIEND_CALL_STATE_FINISHED); - + printf("Success!\n"); } - + toxav_kill(BobAV); toxav_kill(AliceAV); tox_kill(Bob); tox_kill(Alice); tox_kill(bootstrap); - + printf("\nTest successful!\n"); } END_TEST @@ -577,7 +577,7 @@ int main(int argc, char *argv[]) { (void) argc; (void) argv; - + test_AV_flows(); return 0; } @@ -593,7 +593,7 @@ int main(int argc, char *argv[]) { (void) argc; (void) argv; - + Suite *tox = tox_suite(); SRunner *test_runner = srunner_create(tox); diff --git a/auto_tests/toxav_many_test.c b/auto_tests/toxav_many_test.c index 9819b694..ab496024 100644 --- a/auto_tests/toxav_many_test.c +++ b/auto_tests/toxav_many_test.c @@ -42,29 +42,29 @@ typedef struct { } CallControl; typedef struct { - ToxAV* AliceAV; - ToxAV* BobAV; - CallControl* AliceCC; - CallControl* BobCC; + ToxAV *AliceAV; + ToxAV *BobAV; + CallControl *AliceCC; + CallControl *BobCC; uint32_t friend_number; } thread_data; /** - * Callbacks + * Callbacks */ void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data) { (void) av; (void) audio_enabled; (void) video_enabled; - + printf("Handling CALL callback\n"); - ((CallControl*)user_data)[friend_number].incoming = true; + ((CallControl *)user_data)[friend_number].incoming = true; } void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data) { printf("Handling CALL STATE callback: %d %p\n", state, av); - ((CallControl*)user_data)[friend_number].state = state; + ((CallControl *)user_data)[friend_number].state = state; } void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height, @@ -102,6 +102,7 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) { (void) userdata; + if (length == 7 && memcmp("gentoo", data, 7) == 0) { ck_assert(tox_friend_add_norequest(m, public_key, NULL) != (uint32_t) ~0); } @@ -111,92 +112,93 @@ void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t /** * Iterate helper */ -ToxAV* setup_av_instance(Tox* tox, CallControl *CC) +ToxAV *setup_av_instance(Tox *tox, CallControl *CC) { TOXAV_ERR_NEW error; - - ToxAV* av = toxav_new(tox, &error); + + ToxAV *av = toxav_new(tox, &error); ck_assert(error == TOXAV_ERR_NEW_OK); - + toxav_callback_call(av, t_toxav_call_cb, CC); toxav_callback_call_state(av, t_toxav_call_state_cb, CC); toxav_callback_video_receive_frame(av, t_toxav_receive_video_frame_cb, CC); toxav_callback_audio_receive_frame(av, t_toxav_receive_audio_frame_cb, CC); - + return av; } -void* call_thread(void* pd) +void *call_thread(void *pd) { - ToxAV* AliceAV = ((thread_data*) pd)->AliceAV; - ToxAV* BobAV = ((thread_data*) pd)->BobAV; - CallControl* AliceCC = ((thread_data*) pd)->AliceCC; - CallControl* BobCC = ((thread_data*) pd)->BobCC; - uint32_t friend_number = ((thread_data*) pd)->friend_number; - - + ToxAV *AliceAV = ((thread_data *) pd)->AliceAV; + ToxAV *BobAV = ((thread_data *) pd)->BobAV; + CallControl *AliceCC = ((thread_data *) pd)->AliceCC; + CallControl *BobCC = ((thread_data *) pd)->BobCC; + uint32_t friend_number = ((thread_data *) pd)->friend_number; + + memset(AliceCC, 0, sizeof(CallControl)); memset(BobCC, 0, sizeof(CallControl)); - + { /* Call */ TOXAV_ERR_CALL rc; toxav_call(AliceAV, friend_number, 48, 3000, &rc); - + if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); ck_assert(0); } } - + while (!BobCC->incoming) c_sleep(10); - + { /* Answer */ TOXAV_ERR_ANSWER rc; toxav_answer(BobAV, 0, 8, 500, &rc); - + if (rc != TOXAV_ERR_ANSWER_OK) { printf("toxav_answer failed: %d\n", rc); ck_assert(0); } } - + c_sleep(30); - + int16_t PCM[960]; - uint8_t video_y[800*600]; - uint8_t video_u[800*600 / 2]; - uint8_t video_v[800*600 / 2]; - + uint8_t video_y[800 * 600]; + uint8_t video_u[800 * 600 / 2]; + uint8_t video_v[800 * 600 / 2]; + memset(PCM, 0, sizeof(PCM)); memset(video_y, 0, sizeof(video_y)); memset(video_u, 0, sizeof(video_u)); memset(video_v, 0, sizeof(video_v)); - + time_t start_time = time(NULL); - while(time(NULL) - start_time < 4) { + + while (time(NULL) - start_time < 4) { toxav_iterate(AliceAV); toxav_iterate(BobAV); - + toxav_audio_send_frame(AliceAV, friend_number, PCM, 960, 1, 48000, NULL); toxav_audio_send_frame(BobAV, 0, PCM, 960, 1, 48000, NULL); - + toxav_video_send_frame(AliceAV, friend_number, 800, 600, video_y, video_u, video_v, NULL); toxav_video_send_frame(BobAV, 0, 800, 600, video_y, video_u, video_v, NULL); - + c_sleep(10); } - + { /* Hangup */ TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(AliceAV, friend_number, TOXAV_CALL_CONTROL_CANCEL, &rc); - + if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d %p %p\n", rc, AliceAV, BobAV); } } - + c_sleep(30); - + printf ("Closing thread\n"); pthread_exit(NULL); } @@ -204,111 +206,112 @@ void* call_thread(void* pd) START_TEST(test_AV_three_calls) { - Tox* Alice, *bootstrap, *Bobs[3]; - ToxAV* AliceAV, *BobsAV[3]; - + Tox *Alice, *bootstrap, *Bobs[3]; + ToxAV *AliceAV, *BobsAV[3]; + CallControl AliceCC[3], BobsCC[3]; - + { TOX_ERR_NEW error; - + bootstrap = tox_new(NULL, &error); ck_assert(error == TOX_ERR_NEW_OK); - + Alice = tox_new(NULL, &error); ck_assert(error == TOX_ERR_NEW_OK); - + Bobs[0] = tox_new(NULL, &error); ck_assert(error == TOX_ERR_NEW_OK); - + Bobs[1] = tox_new(NULL, &error); ck_assert(error == TOX_ERR_NEW_OK); - + Bobs[2] = tox_new(NULL, &error); ck_assert(error == TOX_ERR_NEW_OK); } - + printf("Created 5 instances of Tox\n"); printf("Preparing network...\n"); long long unsigned int cur_time = time(NULL); - + uint32_t to_compare = 974536; uint8_t address[TOX_ADDRESS_SIZE]; - + tox_callback_friend_request(Alice, t_accept_friend_request_cb, &to_compare); tox_self_get_address(Alice, address); - - + + ck_assert(tox_friend_add(Bobs[0], address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0); ck_assert(tox_friend_add(Bobs[1], address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0); ck_assert(tox_friend_add(Bobs[2], address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0); - + uint8_t off = 1; - + while (1) { tox_iterate(bootstrap); tox_iterate(Alice); tox_iterate(Bobs[0]); tox_iterate(Bobs[1]); tox_iterate(Bobs[2]); - - if (tox_self_get_connection_status(bootstrap) && - tox_self_get_connection_status(Alice) && - tox_self_get_connection_status(Bobs[0]) && - tox_self_get_connection_status(Bobs[1]) && - tox_self_get_connection_status(Bobs[2]) && off) { + + if (tox_self_get_connection_status(bootstrap) && + tox_self_get_connection_status(Alice) && + tox_self_get_connection_status(Bobs[0]) && + tox_self_get_connection_status(Bobs[1]) && + tox_self_get_connection_status(Bobs[2]) && off) { printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); off = 0; } - + if (tox_friend_get_connection_status(Alice, 0, NULL) == TOX_CONNECTION_UDP && - tox_friend_get_connection_status(Alice, 1, NULL) == TOX_CONNECTION_UDP && - tox_friend_get_connection_status(Alice, 2, NULL) == TOX_CONNECTION_UDP && - tox_friend_get_connection_status(Bobs[0], 0, NULL) == TOX_CONNECTION_UDP && - tox_friend_get_connection_status(Bobs[1], 0, NULL) == TOX_CONNECTION_UDP && - tox_friend_get_connection_status(Bobs[2], 0, NULL) == TOX_CONNECTION_UDP) + tox_friend_get_connection_status(Alice, 1, NULL) == TOX_CONNECTION_UDP && + tox_friend_get_connection_status(Alice, 2, NULL) == TOX_CONNECTION_UDP && + tox_friend_get_connection_status(Bobs[0], 0, NULL) == TOX_CONNECTION_UDP && + tox_friend_get_connection_status(Bobs[1], 0, NULL) == TOX_CONNECTION_UDP && + tox_friend_get_connection_status(Bobs[2], 0, NULL) == TOX_CONNECTION_UDP) break; - + c_sleep(20); } - + AliceAV = setup_av_instance(Alice, AliceCC); BobsAV[0] = setup_av_instance(Bobs[0], BobsCC + 0); BobsAV[1] = setup_av_instance(Bobs[1], BobsCC + 1); BobsAV[2] = setup_av_instance(Bobs[2], BobsCC + 2); - + printf("Created 4 instances of ToxAV\n"); printf("All set after %llu seconds!\n", time(NULL) - cur_time); - + thread_data tds[3]; tds[0].AliceAV = AliceAV; tds[0].BobAV = BobsAV[0]; tds[0].AliceCC = AliceCC + 0; tds[0].BobCC = BobsCC + 0; tds[0].friend_number = 0; - + tds[1].AliceAV = AliceAV; tds[1].BobAV = BobsAV[1]; tds[1].AliceCC = AliceCC + 1; tds[1].BobCC = BobsCC + 1; tds[1].friend_number = 1; - + tds[2].AliceAV = AliceAV; tds[2].BobAV = BobsAV[2]; tds[2].AliceCC = AliceCC + 2; tds[2].BobCC = BobsCC + 2; tds[2].friend_number = 2; - + pthread_t tids[3]; (void) pthread_create(tids + 0, NULL, call_thread, tds + 0); (void) pthread_create(tids + 1, NULL, call_thread, tds + 1); (void) pthread_create(tids + 2, NULL, call_thread, tds + 2); - + (void) pthread_detach(tids[0]); (void) pthread_detach(tids[1]); (void) pthread_detach(tids[2]); - + time_t start_time = time(NULL); + while (time(NULL) - start_time < 5) { tox_iterate(Alice); tox_iterate(Bobs[0]); @@ -316,11 +319,11 @@ START_TEST(test_AV_three_calls) tox_iterate(Bobs[2]); c_sleep(20); } - + (void) pthread_join(tids[0], NULL); (void) pthread_join(tids[1], NULL); (void) pthread_join(tids[2], NULL); - + printf ("Killing all instances\n"); toxav_kill(BobsAV[0]); toxav_kill(BobsAV[1]); @@ -331,7 +334,7 @@ START_TEST(test_AV_three_calls) tox_kill(Bobs[2]); tox_kill(Alice); tox_kill(bootstrap); - + printf("\nTest successful!\n"); } END_TEST @@ -342,7 +345,7 @@ int main(int argc, char *argv[]) { (void) argc; (void) argv; - + test_AV_three_calls(); return 0; } @@ -363,7 +366,7 @@ int main(int argc, char *argv[]) { (void) argc; (void) argv; - + Suite *tox = tox_suite(); SRunner *test_runner = srunner_create(tox); diff --git a/testing/av_test.c b/testing/av_test.c index fa6a831f..4b2fe61d 100644 --- a/testing/av_test.c +++ b/testing/av_test.c @@ -16,8 +16,8 @@ * * You should have received a copy of the GNU General Public License * along with Tox. If not, see . - * - * Compile with (Linux only; in newly created directory toxcore/dir_name): + * + * Compile with (Linux only; in newly created directory toxcore/dir_name): * gcc -o av_test ../toxav/av_test.c ../build/.libs/libtox*.a -lopencv_core \ * -lopencv_highgui -lopencv_imgproc -lsndfile -pthread -lvpx -lopus -lsodium -lportaudio */ @@ -75,35 +75,36 @@ typedef struct { bool incoming; uint32_t state; pthread_mutex_t arb_mutex[1]; - RingBuffer* arb; /* Audio ring buffer */ - + RingBuffer *arb; /* Audio ring buffer */ + } CallControl; struct toxav_thread_data { - ToxAV* AliceAV; - ToxAV* BobAV; + ToxAV *AliceAV; + ToxAV *BobAV; int32_t sig; }; -const char* vdout = "AV Test"; /* Video output */ -PaStream* adout = NULL; /* Audio output */ +const char *vdout = "AV Test"; /* Video output */ +PaStream *adout = NULL; /* Audio output */ typedef struct { uint16_t size; int16_t data[]; } frame; -void* pa_write_thread (void* d) +void *pa_write_thread (void *d) { - /* The purpose of this thread is to make sure Pa_WriteStream will not block + /* The purpose of this thread is to make sure Pa_WriteStream will not block * toxav_iterate thread */ - CallControl* cc = d; - + CallControl *cc = d; + while (Pa_IsStreamActive(adout)) { - frame* f; + frame *f; pthread_mutex_lock(cc->arb_mutex); - if (rb_read(cc->arb, (void**)&f)) { + + if (rb_read(cc->arb, (void **)&f)) { pthread_mutex_unlock(cc->arb_mutex); Pa_WriteStream(adout, f->data, f->size); free(f); @@ -115,17 +116,17 @@ void* pa_write_thread (void* d) } /** - * Callbacks + * Callbacks */ void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data) { printf("Handling CALL callback\n"); - ((CallControl*)user_data)->incoming = true; + ((CallControl *)user_data)->incoming = true; } void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data) { printf("Handling CALL STATE callback: %d\n", state); - ((CallControl*)user_data)->state = state; + ((CallControl *)user_data)->state = state; } void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, uint16_t width, uint16_t height, @@ -136,30 +137,31 @@ void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, ystride = abs(ystride); ustride = abs(ustride); vstride = abs(vstride); - + uint16_t *img_data = malloc(height * width * 6); - + unsigned long int i, j; + for (i = 0; i < height; ++i) { for (j = 0; j < width; ++j) { - uint8_t *point = (uint8_t*) img_data + 3 * ((i * width) + j); + uint8_t *point = (uint8_t *) img_data + 3 * ((i * width) + j); int yx = y[(i * ystride) + j]; int ux = u[((i / 2) * ustride) + (j / 2)]; int vx = v[((i / 2) * vstride) + (j / 2)]; - + point[0] = YUV2R(yx, ux, vx); point[1] = YUV2G(yx, ux, vx); point[2] = YUV2B(yx, ux, vx); } } - - + + CvMat mat = cvMat(height, width, CV_8UC3, img_data); - + CvSize sz = {.height = height, .width = width}; - - IplImage* header = cvCreateImageHeader(sz, 1, 3); - IplImage* img = cvGetImage(&mat, header); + + IplImage *header = cvCreateImageHeader(sz, 1, 3); + IplImage *img = cvGetImage(&mat, header); cvShowImage(vdout, img); free(img_data); } @@ -170,16 +172,16 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, uint32_t sampling_rate, void *user_data) { - CallControl* cc = user_data; - frame* f = malloc(sizeof(uint16_t) + sample_count * sizeof(int16_t) * channels); + CallControl *cc = user_data; + frame *f = malloc(sizeof(uint16_t) + sample_count * sizeof(int16_t) * channels); memcpy(f->data, pcm, sample_count * sizeof(int16_t) * channels); f->size = sample_count; - + pthread_mutex_lock(cc->arb_mutex); free(rb_write(cc->arb, f)); pthread_mutex_unlock(cc->arb_mutex); } -void t_toxav_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, +void t_toxav_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, void *user_data) { @@ -194,156 +196,159 @@ void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t /** */ -void initialize_tox(Tox** bootstrap, ToxAV** AliceAV, CallControl* AliceCC, ToxAV** BobAV, CallControl* BobCC) +void initialize_tox(Tox **bootstrap, ToxAV **AliceAV, CallControl *AliceCC, ToxAV **BobAV, CallControl *BobCC) { - Tox* Alice; - Tox* Bob; - + Tox *Alice; + Tox *Bob; + struct Tox_Options opts; tox_options_default(&opts); - + opts.end_port = 0; opts.ipv6_enabled = false; - + { TOX_ERR_NEW error; - + opts.start_port = 33445; *bootstrap = tox_new(&opts, &error); assert(error == TOX_ERR_NEW_OK); - + opts.start_port = 33455; Alice = tox_new(&opts, &error); assert(error == TOX_ERR_NEW_OK); - + opts.start_port = 33465; Bob = tox_new(&opts, &error); assert(error == TOX_ERR_NEW_OK); } - + printf("Created 3 instances of Tox\n"); printf("Preparing network...\n"); long long unsigned int cur_time = time(NULL); - + uint32_t to_compare = 974536; uint8_t address[TOX_ADDRESS_SIZE]; - + tox_callback_friend_request(Alice, t_accept_friend_request_cb, &to_compare); tox_self_get_address(Alice, address); - - + + assert(tox_friend_add(Bob, address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0); - + uint8_t off = 1; - + while (1) { tox_iterate(*bootstrap); tox_iterate(Alice); tox_iterate(Bob); - - if (tox_self_get_connection_status(*bootstrap) && - tox_self_get_connection_status(Alice) && - tox_self_get_connection_status(Bob) && off) { + + if (tox_self_get_connection_status(*bootstrap) && + tox_self_get_connection_status(Alice) && + tox_self_get_connection_status(Bob) && off) { printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); off = 0; } - - if (tox_friend_get_connection_status(Alice, 0, NULL) == TOX_CONNECTION_UDP && - tox_friend_get_connection_status(Bob, 0, NULL) == TOX_CONNECTION_UDP) + + if (tox_friend_get_connection_status(Alice, 0, NULL) == TOX_CONNECTION_UDP && + tox_friend_get_connection_status(Bob, 0, NULL) == TOX_CONNECTION_UDP) break; - + c_sleep(20); } - - + + TOXAV_ERR_NEW rc; *AliceAV = toxav_new(Alice, &rc); assert(rc == TOXAV_ERR_NEW_OK); - + *BobAV = toxav_new(Bob, &rc); assert(rc == TOXAV_ERR_NEW_OK); - - + + /* Alice */ toxav_callback_call(*AliceAV, t_toxav_call_cb, AliceCC); toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC); toxav_callback_bit_rate_status(*AliceAV, t_toxav_bit_rate_status_cb, AliceCC); toxav_callback_video_receive_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC); toxav_callback_audio_receive_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC); - + /* Bob */ toxav_callback_call(*BobAV, t_toxav_call_cb, BobCC); toxav_callback_call_state(*BobAV, t_toxav_call_state_cb, BobCC); toxav_callback_bit_rate_status(*BobAV, t_toxav_bit_rate_status_cb, BobCC); toxav_callback_video_receive_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC); toxav_callback_audio_receive_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC); - - + + printf("Created 2 instances of ToxAV\n"); printf("All set after %llu seconds!\n", time(NULL) - cur_time); } -int iterate_tox(Tox* bootstrap, ToxAV* AliceAV, ToxAV* BobAV) +int iterate_tox(Tox *bootstrap, ToxAV *AliceAV, ToxAV *BobAV) { tox_iterate(bootstrap); tox_iterate(toxav_get_tox(AliceAV)); tox_iterate(toxav_get_tox(BobAV)); - + return MIN(tox_iteration_interval(toxav_get_tox(AliceAV)), tox_iteration_interval(toxav_get_tox(BobAV))); } -void* iterate_toxav (void * data) +void *iterate_toxav (void *data) { - struct toxav_thread_data* data_cast = data; + struct toxav_thread_data *data_cast = data; #if defined TEST_TRANSFER_V && TEST_TRANSFER_V == 1 cvNamedWindow(vdout, CV_WINDOW_AUTOSIZE); #endif - + while (data_cast->sig == 0) { toxav_iterate(data_cast->AliceAV); toxav_iterate(data_cast->BobAV); int rc = MIN(toxav_iteration_interval(data_cast->AliceAV), toxav_iteration_interval(data_cast->BobAV)); - + printf("\rIteration interval: %d ", rc); fflush(stdout); - + #if defined TEST_TRANSFER_V && TEST_TRANSFER_V == 1 + if (!rc) rc = 1; - + cvWaitKey(rc); #else c_sleep(rc); #endif } - + data_cast->sig = 1; - + #if defined TEST_TRANSFER_V && TEST_TRANSFER_V == 1 cvDestroyWindow(vdout); #endif - + pthread_exit(NULL); } -int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img) -{ +int send_opencv_img(ToxAV *av, uint32_t friend_number, const IplImage *img) +{ int32_t strides[3] = { 1280, 640, 640 }; - uint8_t* planes[3] = { + uint8_t *planes[3] = { malloc(img->height * img->width), malloc(img->height * img->width / 4), malloc(img->height * img->width / 4), }; - + int x_chroma_shift = 1; int y_chroma_shift = 1; - + int x, y; + for (y = 0; y < img->height; ++y) { for (x = 0; x < img->width; ++x) { uint8_t r = img->imageData[(x + y * img->width) * 3 + 0]; uint8_t g = img->imageData[(x + y * img->width) * 3 + 1]; uint8_t b = img->imageData[(x + y * img->width) * 3 + 2]; - + planes[0][x + y * strides[0]] = RGB2Y(r, g, b); + if (!(x % (1 << x_chroma_shift)) && !(y % (1 << y_chroma_shift))) { const int i = x / (1 << x_chroma_shift); const int j = y / (1 << y_chroma_shift); @@ -363,15 +368,17 @@ int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img) int print_audio_devices() { int i = 0; + for (i = 0; i < Pa_GetDeviceCount(); ++i) { - const PaDeviceInfo* info = Pa_GetDeviceInfo(i); + const PaDeviceInfo *info = Pa_GetDeviceInfo(i); + if (info) printf("%d) %s\n", i, info->name); } - + return 0; } -int print_help (const char* name) +int print_help (const char *name) { printf("Usage: %s -[a:v:o:dh]\n" "-a audio input file\n" @@ -381,351 +388,379 @@ int print_help (const char* name) "-o output audio device index\n" "-d print output audio devices\n" "-h print this help\n", name); - + return 0; } -int main (int argc, char** argv) -{ +int main (int argc, char **argv) +{ freopen("/dev/zero", "w", stderr); Pa_Initialize(); - + struct stat st; - + /* AV files for testing */ - const char* af_name = NULL; - const char* vf_name = NULL; + const char *af_name = NULL; + const char *vf_name = NULL; long audio_out_dev_idx = -1; - + int32_t audio_frame_duration = 20; int32_t video_frame_duration = 10; - + /* Parse settings */ - CHECK_ARG: switch (getopt(argc, argv, "a:b:v:x:o:dh")) { - case 'a': - af_name = optarg; - goto CHECK_ARG; - case 'b':{ - char *d; - audio_frame_duration = strtol(optarg, &d, 10); - if (*d) { - printf("Invalid value for argument: 'b'"); - exit(1); +CHECK_ARG: + + switch (getopt(argc, argv, "a:b:v:x:o:dh")) { + case 'a': + af_name = optarg; + goto CHECK_ARG; + + case 'b': { + char *d; + audio_frame_duration = strtol(optarg, &d, 10); + + if (*d) { + printf("Invalid value for argument: 'b'"); + exit(1); + } + + goto CHECK_ARG; } - goto CHECK_ARG; - } - case 'v': - vf_name = optarg; - goto CHECK_ARG; - case 'x':{ - char *d; - video_frame_duration = strtol(optarg, &d, 10); - if (*d) { - printf("Invalid value for argument: 'x'"); - exit(1); + + case 'v': + vf_name = optarg; + goto CHECK_ARG; + + case 'x': { + char *d; + video_frame_duration = strtol(optarg, &d, 10); + + if (*d) { + printf("Invalid value for argument: 'x'"); + exit(1); + } + + goto CHECK_ARG; } - goto CHECK_ARG; - } - case 'o': { - char *d; - audio_out_dev_idx = strtol(optarg, &d, 10); - if (*d) { - printf("Invalid value for argument: 'o'"); - exit(1); + + case 'o': { + char *d; + audio_out_dev_idx = strtol(optarg, &d, 10); + + if (*d) { + printf("Invalid value for argument: 'o'"); + exit(1); + } + + goto CHECK_ARG; } - goto CHECK_ARG; + + case 'd': + return print_audio_devices(); + + case 'h': + return print_help(argv[0]); + + case '?': + exit(1); + + case -1: + ; } - case 'd': - return print_audio_devices(); - case 'h': - return print_help(argv[0]); - case '?': - exit(1); - case -1:; - } - + { /* Check files */ if (!af_name) { printf("Required audio input file!\n"); exit(1); } - + if (!vf_name) { printf("Required video input file!\n"); exit(1); } - + /* Check for files */ - if(stat(af_name, &st) != 0 || !S_ISREG(st.st_mode)) - { + if (stat(af_name, &st) != 0 || !S_ISREG(st.st_mode)) { printf("%s doesn't seem to be a regular file!\n", af_name); exit(1); } - - if(stat(vf_name, &st) != 0 || !S_ISREG(st.st_mode)) - { + + if (stat(vf_name, &st) != 0 || !S_ISREG(st.st_mode)) { printf("%s doesn't seem to be a regular file!\n", vf_name); exit(1); } } - + if (audio_out_dev_idx < 0) audio_out_dev_idx = Pa_GetDefaultOutputDevice(); - - const PaDeviceInfo* audio_dev = Pa_GetDeviceInfo(audio_out_dev_idx); + + const PaDeviceInfo *audio_dev = Pa_GetDeviceInfo(audio_out_dev_idx); + if (!audio_dev) { fprintf(stderr, "Device under index: %ld invalid", audio_out_dev_idx); return 1; } - + printf("Using audio device: %s\n", audio_dev->name); printf("Using audio file: %s\n", af_name); printf("Using video file: %s\n", vf_name); - + /* START TOX NETWORK */ - + Tox *bootstrap; ToxAV *AliceAV; ToxAV *BobAV; - + CallControl AliceCC; CallControl BobCC; - + initialize_tox(&bootstrap, &AliceAV, &AliceCC, &BobAV, &BobCC); - + if (TEST_TRANSFER_A) { - SNDFILE* af_handle; + SNDFILE *af_handle; SF_INFO af_info; - - printf("\nTrying audio enc/dec...\n"); - - memset(&AliceCC, 0, sizeof(CallControl)); + + printf("\nTrying audio enc/dec...\n"); + + memset(&AliceCC, 0, sizeof(CallControl)); memset(&BobCC, 0, sizeof(CallControl)); - + pthread_mutex_init(AliceCC.arb_mutex, NULL); pthread_mutex_init(BobCC.arb_mutex, NULL); - + AliceCC.arb = rb_new(16); BobCC.arb = rb_new(16); - + { /* Call */ TOXAV_ERR_CALL rc; toxav_call(AliceAV, 0, 48, 0, &rc); - + if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); exit(1); } } - + while (!BobCC.incoming) iterate_tox(bootstrap, AliceAV, BobAV); - - { /* Answer */ + + { /* Answer */ TOXAV_ERR_ANSWER rc; toxav_answer(BobAV, 0, 48, 0, &rc); - + if (rc != TOXAV_ERR_ANSWER_OK) { printf("toxav_answer failed: %d\n", rc); exit(1); } } - + while (AliceCC.state == 0) iterate_tox(bootstrap, AliceAV, BobAV); - + /* Open audio file */ af_handle = sf_open(af_name, SFM_READ, &af_info); + if (af_handle == NULL) { printf("Failed to open the file.\n"); exit(1); } - + int16_t PCM[5760]; - + time_t start_time = time(NULL); time_t expected_time = af_info.frames / af_info.samplerate + 2; - - + + /* Start decode thread */ struct toxav_thread_data data = { .AliceAV = AliceAV, .BobAV = BobAV, .sig = 0 }; - + pthread_t dect; pthread_create(&dect, NULL, iterate_toxav, &data); pthread_detach(dect); - + int frame_size = (af_info.samplerate * audio_frame_duration / 1000) * af_info.channels; - + struct PaStreamParameters output; output.device = audio_out_dev_idx; output.channelCount = af_info.channels; output.sampleFormat = paInt16; output.suggestedLatency = audio_dev->defaultHighOutputLatency; output.hostApiSpecificStreamInfo = NULL; - + PaError err = Pa_OpenStream(&adout, NULL, &output, af_info.samplerate, frame_size, paNoFlag, NULL, NULL); assert(err == paNoError); - + err = Pa_StartStream(adout); assert(err == paNoError); - + // toxav_audio_bit_rate_set(AliceAV, 0, 64, false, NULL); - + /* Start write thread */ pthread_t t; pthread_create(&t, NULL, pa_write_thread, &BobCC); pthread_detach(t); - + printf("Sample rate %d\n", af_info.samplerate); - while (start_time + expected_time > time(NULL) ) { + + while (start_time + expected_time > time(NULL) ) { uint64_t enc_start_time = current_time_monotonic(); int64_t count = sf_read_short(af_handle, PCM, frame_size); + if (count > 0) { TOXAV_ERR_SEND_FRAME rc; - if (toxav_audio_send_frame(AliceAV, 0, PCM, count/af_info.channels, af_info.channels, af_info.samplerate, &rc) == false) { + + if (toxav_audio_send_frame(AliceAV, 0, PCM, count / af_info.channels, af_info.channels, af_info.samplerate, + &rc) == false) { printf("Error sending frame of size %ld: %d\n", count, rc); } } + iterate_tox(bootstrap, AliceAV, BobAV); c_sleep(abs(audio_frame_duration - (current_time_monotonic() - enc_start_time) - 1)); - } - - printf("Played file in: %lu; stopping stream...\n", time(NULL) - start_time); - + } + + printf("Played file in: %lu; stopping stream...\n", time(NULL) - start_time); + Pa_StopStream(adout); sf_close(af_handle); - - { /* Hangup */ + + { /* Hangup */ TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); - + if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d\n", rc); exit(1); } } - + iterate_tox(bootstrap, AliceAV, BobAV); assert(BobCC.state == TOXAV_FRIEND_CALL_STATE_FINISHED); - + /* Stop decode thread */ data.sig = -1; - while(data.sig != 1) + + while (data.sig != 1) pthread_yield(); - + pthread_mutex_destroy(AliceCC.arb_mutex); pthread_mutex_destroy(BobCC.arb_mutex); - - void* f = NULL; - while(rb_read(AliceCC.arb, &f)) + + void *f = NULL; + + while (rb_read(AliceCC.arb, &f)) free(f); - - while(rb_read(BobCC.arb, &f)) + + while (rb_read(BobCC.arb, &f)) free(f); - - printf("Success!"); - } - - if (TEST_TRANSFER_V) { + + printf("Success!"); + } + + if (TEST_TRANSFER_V) { printf("\nTrying video enc/dec...\n"); - + memset(&AliceCC, 0, sizeof(CallControl)); memset(&BobCC, 0, sizeof(CallControl)); - + { /* Call */ TOXAV_ERR_CALL rc; toxav_call(AliceAV, 0, 0, 2000, &rc); - + if (rc != TOXAV_ERR_CALL_OK) { printf("toxav_call failed: %d\n", rc); exit(1); } } - + while (!BobCC.incoming) iterate_tox(bootstrap, AliceAV, BobAV); - + { /* Answer */ TOXAV_ERR_ANSWER rc; toxav_answer(BobAV, 0, 0, 5000, &rc); - + if (rc != TOXAV_ERR_ANSWER_OK) { printf("toxav_answer failed: %d\n", rc); exit(1); } } - + iterate_tox(bootstrap, AliceAV, BobAV); - + /* Start decode thread */ struct toxav_thread_data data = { .AliceAV = AliceAV, .BobAV = BobAV, .sig = 0 }; - + pthread_t dect; pthread_create(&dect, NULL, iterate_toxav, &data); pthread_detach(dect); - - CvCapture* capture = cvCreateFileCapture(vf_name); + + CvCapture *capture = cvCreateFileCapture(vf_name); + if (!capture) { printf("Failed to open video file: %s\n", vf_name); exit(1); } - + // toxav_video_bit_rate_set(AliceAV, 0, 5000, false, NULL); - + time_t start_time = time(NULL); - while(start_time + 90 > time(NULL)) { - IplImage* frame = cvQueryFrame(capture ); + + while (start_time + 90 > time(NULL)) { + IplImage *frame = cvQueryFrame(capture ); + if (!frame) break; - + send_opencv_img(AliceAV, 0, frame); iterate_tox(bootstrap, AliceAV, BobAV); c_sleep(10); } - + cvReleaseCapture(&capture); - + { /* Hangup */ TOXAV_ERR_CALL_CONTROL rc; toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); - + if (rc != TOXAV_ERR_CALL_CONTROL_OK) { printf("toxav_call_control failed: %d\n", rc); exit(1); } } - + iterate_tox(bootstrap, AliceAV, BobAV); assert(BobCC.state == TOXAV_FRIEND_CALL_STATE_FINISHED); - + /* Stop decode thread */ printf("Stopping decode thread\n"); data.sig = -1; - while(data.sig != 1) + + while (data.sig != 1) pthread_yield(); - + printf("Success!"); } - - - Tox* Alice = toxav_get_tox(AliceAV); - Tox* Bob = toxav_get_tox(BobAV); + + + Tox *Alice = toxav_get_tox(AliceAV); + Tox *Bob = toxav_get_tox(BobAV); toxav_kill(BobAV); toxav_kill(AliceAV); tox_kill(Bob); tox_kill(Alice); tox_kill(bootstrap); - + printf("\nTest successful!\n"); - + Pa_Terminate(); return 0; } diff --git a/toxav/audio.c b/toxav/audio.c index 4f9d3562..ad543502 100644 --- a/toxav/audio.c +++ b/toxav/audio.c @@ -76,11 +76,11 @@ ACSession *ac_new(ToxAV *av, uint32_t friend_number, toxav_audio_receive_frame_c if (ac->encoder == NULL) goto DECODER_CLEANUP; - + ac->le_bit_rate = 48000; ac->le_sample_rate = 48000; ac->le_channel_count = 2; - + ac->ld_channel_count = 2; ac->ld_sample_rate = 48000; ac->ldrts = 0; /* Make it possible to reconfigure straight away */ @@ -126,7 +126,7 @@ void ac_iterate(ACSession *ac) return; /* TODO fix this and jitter buffering */ - + /* Enough space for the maximum frame size (120 ms 48 KHz stereo audio) */ int16_t tmp[5760 * 2]; @@ -221,9 +221,9 @@ int ac_queue_message(void *acp, struct RTPMessage *msg) } int ac_reconfigure_encoder(ACSession *ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels) { - if (!ac || !reconfigure_audio_encoder(&ac->encoder, bit_rate, + if (!ac || !reconfigure_audio_encoder(&ac->encoder, bit_rate, sampling_rate, channels, - &ac->le_bit_rate, + &ac->le_bit_rate, &ac->le_sample_rate, &ac->le_channel_count)) return -1; diff --git a/toxav/bwcontroler.c b/toxav/bwcontroler.c index 2530e7fd..9dd15c93 100644 --- a/toxav/bwcontroler.c +++ b/toxav/bwcontroler.c @@ -34,7 +34,7 @@ #define BWC_AVG_PKT_COUNT 20 /** - * + * */ struct BWControler_s { @@ -77,10 +77,11 @@ BWControler *bwc_new(Messenger *m, uint32_t friendnumber, /* Fill with zeros */ int i = 0; + for (; i < BWC_AVG_PKT_COUNT; i ++) rb_write(retu->rcvpkt.rb, retu->rcvpkt.rb_s + i); - - m_callback_rtp_packet(m, friendnumber, BWC_PACKET_ID, bwc_handle_data, retu); + + m_callback_rtp_packet(m, friendnumber, BWC_PACKET_ID, bwc_handle_data, retu); return retu; } @@ -88,19 +89,19 @@ void bwc_kill(BWControler *bwc) { if (!bwc) return; - + m_callback_rtp_packet(bwc->m, bwc->friend_number, BWC_PACKET_ID, NULL, NULL); - + rb_kill(bwc->rcvpkt.rb); free(bwc); } -void bwc_feed_avg(BWControler* bwc, uint32_t bytes) +void bwc_feed_avg(BWControler *bwc, uint32_t bytes) { uint32_t *p; - - rb_read(bwc->rcvpkt.rb, (void**) &p); + + rb_read(bwc->rcvpkt.rb, (void **) &p); rb_write(bwc->rcvpkt.rb, p); - + *p = bytes; } void bwc_add_lost(BWControler *bwc, uint32_t bytes) @@ -109,21 +110,22 @@ void bwc_add_lost(BWControler *bwc, uint32_t bytes) return; if (!bytes) { - uint32_t* t_avg[BWC_AVG_PKT_COUNT], c = 1; - - rb_data(bwc->rcvpkt.rb, (void**) t_avg); - + uint32_t *t_avg[BWC_AVG_PKT_COUNT], c = 1; + + rb_data(bwc->rcvpkt.rb, (void **) t_avg); + int i = 0; + for (; i < BWC_AVG_PKT_COUNT; i ++) { bytes += *(t_avg[i]); - + if (*(t_avg[i])) c++; } - + bytes /= c; } - + bwc->cycle.lost += bytes; send_update(bwc); } @@ -131,7 +133,7 @@ void bwc_add_recv(BWControler *bwc, uint32_t bytes) { if (!bwc || !bytes) return; - + bwc->cycle.recv += bytes; send_update(bwc); } @@ -145,21 +147,19 @@ struct BWCMessage { void send_update(BWControler *bwc) { if (current_time_monotonic() - bwc->cycle.lfu > BWC_REFRESH_INTERVAL_MS) { - + bwc->cycle.lost /= 10; bwc->cycle.recv /= 10; bwc->cycle.lfu = current_time_monotonic(); - } - else if (current_time_monotonic() - bwc->cycle.lsu > BWC_SEND_INTERVAL_MS) { - - if (bwc->cycle.lost) - { + } else if (current_time_monotonic() - bwc->cycle.lsu > BWC_SEND_INTERVAL_MS) { + + if (bwc->cycle.lost) { LOGGER_DEBUG ("%p Sent update rcv: %u lost: %u", bwc, bwc->cycle.recv, bwc->cycle.lost); uint8_t p_msg[sizeof(struct BWCMessage) + 1]; - struct BWCMessage* b_msg = (struct BWCMessage*)(p_msg + 1); - + struct BWCMessage *b_msg = (struct BWCMessage *)(p_msg + 1); + p_msg[0] = BWC_PACKET_ID; b_msg->lost = htonl(bwc->cycle.lost); b_msg->recv = htonl(bwc->cycle.recv); @@ -167,27 +167,27 @@ void send_update(BWControler *bwc) if (-1 == send_custom_lossy_packet(bwc->m, bwc->friend_number, p_msg, sizeof(p_msg))) LOGGER_WARNING("BWC send failed (len: %d)! std error: %s", sizeof(p_msg), strerror(errno)); } - + bwc->cycle.lsu = current_time_monotonic(); } } int on_update (BWControler *bwc, struct BWCMessage *msg) { LOGGER_DEBUG ("%p Got update from peer", bwc); - + /* Peer must respect time boundary */ if (current_time_monotonic() < bwc->cycle.lru + BWC_SEND_INTERVAL_MS) { LOGGER_DEBUG("%p Rejecting extra update", bwc); return -1; } - + bwc->cycle.lru = current_time_monotonic(); msg->recv = ntohl(msg->recv); msg->lost = ntohl(msg->lost); - + LOGGER_DEBUG ("recved: %u lost: %u", msg->recv, msg->lost); - + if (msg->lost && bwc->mcb) bwc->mcb(bwc, bwc->friend_number, ((float) (msg->lost) / (msg->recv + msg->lost)), @@ -195,7 +195,7 @@ int on_update (BWControler *bwc, struct BWCMessage *msg) return 0; } -int bwc_handle_data(Messenger* m, uint32_t friendnumber, const uint8_t* data, uint16_t length, void* object) +int bwc_handle_data(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object) { if (length - 1 != sizeof(struct BWCMessage)) return -1; diff --git a/toxav/msi.c b/toxav/msi.c index 7ad39a54..c08c0135 100644 --- a/toxav/msi.c +++ b/toxav/msi.c @@ -99,7 +99,7 @@ void msi_register_callback (MSISession *session, msi_action_cb *callback, MSICal { if (!session) return; - + pthread_mutex_lock(session->mutex); session->callbacks[id] = callback; pthread_mutex_unlock(session->mutex); @@ -142,7 +142,7 @@ int msi_kill (MSISession *session) } m_callback_msi_packet((struct Messenger *) session->messenger, NULL, NULL); - + if (pthread_mutex_trylock(session->mutex) != 0) { LOGGER_ERROR ("Failed to aquire lock on msi mutex"); return -1; @@ -171,7 +171,7 @@ int msi_invite (MSISession *session, MSICall **call, uint32_t friend_number, uin { if (!session) return -1; - + LOGGER_DEBUG("Session: %p Inviting friend: %u", session, friend_number); if (pthread_mutex_trylock(session->mutex) != 0) { @@ -212,11 +212,11 @@ int msi_hangup (MSICall *call) { if (!call || !call->session) return -1; - + LOGGER_DEBUG("Session: %p Hanging up call with friend: %u", call->session, call->friend_number); MSISession *session = call->session; - + if (pthread_mutex_trylock(session->mutex) != 0) { LOGGER_ERROR ("Failed to aquire lock on msi mutex"); return -1; @@ -278,7 +278,7 @@ int msi_change_capabilities(MSICall *call, uint8_t capabilities) { if (!call || !call->session) return -1; - + LOGGER_DEBUG("Session: %p Trying to change capabilities to friend %u", call->session, call->friend_number); MSISession *session = call->session; @@ -619,19 +619,18 @@ void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void * break; } } -void handle_init (MSICall* call, const MSIMessage* msg) +void handle_init (MSICall *call, const MSIMessage *msg) { assert(call); LOGGER_DEBUG("Session: %p Handling 'init' friend: %d", call->session, call->friend_number); - + if (!msg->capabilities.exists) { LOGGER_WARNING("Session: %p Invalid capabilities on 'init'"); call->error = msi_EInvalidMessage; goto FAILURE; } - - switch (call->state) - { + + switch (call->state) { case msi_CallInactive: { /* Call requested */ call->peer_capabilities = msg->capabilities.value; @@ -641,7 +640,7 @@ void handle_init (MSICall* call, const MSIMessage* msg) goto FAILURE; } break; - + case msi_CallActive: { /* If peer sent init while the call is already * active it's probable that he is trying to @@ -649,9 +648,9 @@ void handle_init (MSICall* call, const MSIMessage* msg) * on our side. We can assume that in this case * we can automatically answer the re-call. */ - + LOGGER_INFO("Friend is recalling us"); - + MSIMessage msg; msg_init(&msg, requ_push); @@ -665,7 +664,7 @@ void handle_init (MSICall* call, const MSIMessage* msg) */ } break; - + default: { LOGGER_WARNING("Session: %p Invalid state on 'init'"); call->error = msi_EInvalidState; @@ -673,7 +672,7 @@ void handle_init (MSICall* call, const MSIMessage* msg) } break; } - + return; FAILURE: send_error(call->session->messenger, call->friend_number, call->error); @@ -746,33 +745,33 @@ void handle_pop (MSICall *call, const MSIMessage *msg) invoke_callback(call, msi_OnError); } else switch (call->state) { - case msi_CallInactive: { - LOGGER_ERROR("Handling what should be impossible case"); - abort(); - } - break; + case msi_CallInactive: { + LOGGER_ERROR("Handling what should be impossible case"); + abort(); + } + break; - case msi_CallActive: { - /* Hangup */ - LOGGER_INFO("Friend hung up on us"); - invoke_callback(call, msi_OnEnd); - } - break; + case msi_CallActive: { + /* Hangup */ + LOGGER_INFO("Friend hung up on us"); + invoke_callback(call, msi_OnEnd); + } + break; - case msi_CallRequesting: { - /* Reject */ - LOGGER_INFO("Friend rejected our call"); - invoke_callback(call, msi_OnEnd); - } - break; + case msi_CallRequesting: { + /* Reject */ + LOGGER_INFO("Friend rejected our call"); + invoke_callback(call, msi_OnEnd); + } + break; - case msi_CallRequested: { - /* Cancel */ - LOGGER_INFO("Friend canceled call invite"); - invoke_callback(call, msi_OnEnd); + case msi_CallRequested: { + /* Cancel */ + LOGGER_INFO("Friend canceled call invite"); + invoke_callback(call, msi_OnEnd); + } + break; } - break; - } kill_call (call); } @@ -814,9 +813,11 @@ void handle_msi_packet (Messenger *m, uint32_t friend_number, const uint8_t *dat case requ_init: handle_init(call, &msg); break; + case requ_push: handle_push(call, &msg); break; + case requ_pop: handle_pop(call, &msg); /* always kills the call */ break; diff --git a/toxav/rtp.c b/toxav/rtp.c index 763166cd..1813725a 100644 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -189,17 +189,18 @@ bool chloss (const RTPSession *session, const struct RTPHeader *header) { if (ntohl(header->timestamp) < session->rtimestamp) { uint16_t hosq, lost = 0; - + hosq = ntohs(header->sequnum); - - lost = (hosq > session->rsequnum) ? - (session->rsequnum + 65535) - hosq : - session->rsequnum - hosq; - + + lost = (hosq > session->rsequnum) ? + (session->rsequnum + 65535) - hosq : + session->rsequnum - hosq; + puts ("Lost packet"); + while (lost --) - bwc_add_lost(session->bwc ,0); - + bwc_add_lost(session->bwc , 0); + return true; } @@ -251,7 +252,7 @@ int handle_rtp_packet (Messenger *m, uint32_t friendnumber, const uint8_t *data, } bwc_feed_avg(session->bwc, length); - + if (ntohs(header->tlen) == length - sizeof (struct RTPHeader)) { /* The message is sent in single part */ @@ -267,7 +268,7 @@ int handle_rtp_packet (Messenger *m, uint32_t friendnumber, const uint8_t *data, } bwc_add_recv(session->bwc, length); - + /* Invoke processing of active multiparted message */ if (session->mp) { if (session->mcb) @@ -341,11 +342,11 @@ int handle_rtp_packet (Messenger *m, uint32_t friendnumber, const uint8_t *data, /* Measure missing parts of the old message */ bwc_add_lost(session->bwc, (session->mp->header.tlen - session->mp->len) + - + /* Must account sizes of rtp headers too */ ((session->mp->header.tlen - session->mp->len) / - MAX_CRYPTO_DATA_SIZE) * sizeof(struct RTPHeader) ); - + MAX_CRYPTO_DATA_SIZE) * sizeof(struct RTPHeader) ); + /* Push the previous message for processing */ if (session->mcb) session->mcb (session->cs, session->mp); diff --git a/toxav/toxav.c b/toxav/toxav.c index 6a17f55d..9eda3412 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -190,7 +190,7 @@ void toxav_kill(ToxAV *av) return; pthread_mutex_lock(av->mutex); - + /* To avoid possible deadlocks */ while (av->msi && msi_kill(av->msi) != 0) { pthread_mutex_unlock(av->mutex); @@ -206,10 +206,10 @@ void toxav_kill(ToxAV *av) it = call_remove(it); /* This will eventually free av->calls */ } } - + pthread_mutex_unlock(av->mutex); pthread_mutex_destroy(av->mutex); - + free(av); } Tox *toxav_get_tox(const ToxAV *av) @@ -277,11 +277,11 @@ bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint TOXAV_ERR_CALL *error) { TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK; - + pthread_mutex_lock(av->mutex); - + if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate)) - || (video_bit_rate && video_bit_rate_invalid(video_bit_rate))) { + || (video_bit_rate && video_bit_rate_invalid(video_bit_rate))) { rc = TOXAV_ERR_CALL_INVALID_BIT_RATE; goto END; } @@ -311,7 +311,7 @@ bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint END: pthread_mutex_unlock(av->mutex); - + if (error) *error = rc; @@ -337,7 +337,7 @@ bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, ui } if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate)) - || (video_bit_rate && video_bit_rate_invalid(video_bit_rate)) + || (video_bit_rate && video_bit_rate_invalid(video_bit_rate)) ) { rc = TOXAV_ERR_ANSWER_INVALID_BIT_RATE; goto END; @@ -441,9 +441,10 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co case TOXAV_CALL_CONTROL_CANCEL: { /* Hang up */ pthread_mutex_lock(call->mutex); + if (msi_hangup(call->msi_call) != 0) { rc = TOXAV_ERR_CALL_CONTROL_SYNC; - pthread_mutex_unlock(call->mutex); + pthread_mutex_unlock(call->mutex); goto END; } @@ -566,18 +567,22 @@ bool toxav_bit_rate_set(ToxAV *av, uint32_t friend_number, int32_t audio_bit_rat LOGGER_DEBUG("Audio bitrate already set to: %d", audio_bit_rate); } else if (audio_bit_rate == 0) { LOGGER_DEBUG("Turned off audio sending"); + if (msi_change_capabilities(call->msi_call, call->msi_call-> self_capabilities ^ msi_CapSAudio) != 0) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_BIT_RATE_SET_SYNC; goto END; } + /* Audio sending is turned off; notify peer */ call->audio_bit_rate = 0; } else { pthread_mutex_lock(call->mutex); + if (call->audio_bit_rate == 0) { LOGGER_DEBUG("Turned on audio sending"); + /* The audio has been turned off before this */ if (msi_change_capabilities(call->msi_call, call-> msi_call->self_capabilities | msi_CapSAudio) != 0) { @@ -588,6 +593,7 @@ bool toxav_bit_rate_set(ToxAV *av, uint32_t friend_number, int32_t audio_bit_rat } } else LOGGER_DEBUG("Set new audio bit rate %d", audio_bit_rate); + call->audio_bit_rate = audio_bit_rate; pthread_mutex_unlock(call->mutex); } @@ -600,6 +606,7 @@ bool toxav_bit_rate_set(ToxAV *av, uint32_t friend_number, int32_t audio_bit_rat LOGGER_DEBUG("Video bitrate already set to: %d", video_bit_rate); } else if (video_bit_rate == 0) { LOGGER_DEBUG("Turned off video sending"); + /* Video sending is turned off; notify peer */ if (msi_change_capabilities(call->msi_call, call->msi_call-> self_capabilities ^ msi_CapSVideo) != 0) { @@ -607,11 +614,14 @@ bool toxav_bit_rate_set(ToxAV *av, uint32_t friend_number, int32_t audio_bit_rat rc = TOXAV_ERR_BIT_RATE_SET_SYNC; goto END; } + call->video_bit_rate = 0; } else { pthread_mutex_lock(call->mutex); + if (call->video_bit_rate == 0) { LOGGER_DEBUG("Turned on video sending"); + /* The video has been turned off before this */ if (msi_change_capabilities(call->msi_call, call-> msi_call->self_capabilities | msi_CapSVideo) != 0) { @@ -622,13 +632,15 @@ bool toxav_bit_rate_set(ToxAV *av, uint32_t friend_number, int32_t audio_bit_rat } } else LOGGER_DEBUG("Set new video bit rate %d", video_bit_rate); + call->video_bit_rate = video_bit_rate; pthread_mutex_unlock(call->mutex); } } - + pthread_mutex_unlock(av->mutex); END: + if (error) *error = rc; @@ -656,7 +668,7 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc rc = TOXAV_ERR_SEND_FRAME_SYNC; goto END; } - + call = call_get(av, friend_number); if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { @@ -719,6 +731,7 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc pthread_mutex_unlock(call->mutex_audio); END: + if (error) *error = rc; @@ -739,7 +752,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u rc = TOXAV_ERR_SEND_FRAME_SYNC; goto END; } - + call = call_get(av, friend_number); if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { @@ -817,6 +830,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u pthread_mutex_unlock(call->mutex_video); END: + if (error) *error = rc; @@ -843,7 +857,7 @@ void toxav_callback_video_receive_frame(ToxAV *av, toxav_video_receive_frame_cb * :: Internal * ******************************************************************************/ -void callback_bwc(BWControler* bwc, uint32_t friend_number, float loss, void* user_data) +void callback_bwc(BWControler *bwc, uint32_t friend_number, float loss, void *user_data) { /* Callback which is called when the internal measure mechanism reported packet loss. * We report suggested lowered bitrate to an app. If app is sending both audio and video, @@ -851,22 +865,23 @@ void callback_bwc(BWControler* bwc, uint32_t friend_number, float loss, void* us * takes more than 90% bandwidth. Otherwise, we report lowered bitrate on audio. * The application may choose to disable video totally if the stream is too bad. */ - - ToxAVCall* call = user_data; + + ToxAVCall *call = user_data; assert(call); - LOGGER_DEBUG("Reported loss of %f%%", loss*100); - + LOGGER_DEBUG("Reported loss of %f%%", loss * 100); + if (loss < .01f) return; pthread_mutex_lock(call->av->mutex); + if (!call->av->bcb.first) { pthread_mutex_unlock(call->av->mutex); LOGGER_WARNING("No callback to report loss on"); return; } - + if (call->video_bit_rate) (*call->av->bcb.first) (call->av, friend_number, call->audio_bit_rate, call->video_bit_rate - (call->video_bit_rate * loss), @@ -875,7 +890,7 @@ void callback_bwc(BWControler* bwc, uint32_t friend_number, float loss, void* us (*call->av->bcb.first) (call->av, friend_number, call->audio_bit_rate - (call->audio_bit_rate * loss), 0, call->av->bcb.second); - + pthread_mutex_unlock(call->av->mutex); } int callback_invite(void *toxav_inst, MSICall *call) @@ -1167,7 +1182,7 @@ bool call_prepare_transmission(ToxAVCall *call) /* Prepare bwc */ call->bwc = bwc_new(av->m, call->friend_number, callback_bwc, call); - + { /* Prepare audio */ call->audio.second = ac_new(av, call->friend_number, av->acb.first, av->acb.second); @@ -1236,7 +1251,7 @@ void call_kill_transmission(ToxAVCall *call) pthread_mutex_unlock(call->mutex); bwc_kill(call->bwc); - + rtp_kill(call->audio.first); ac_kill(call->audio.second); call->audio.first = NULL; diff --git a/toxav/toxav.h b/toxav/toxav.h index 5c5195b3..08a6d265 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h @@ -1,5 +1,5 @@ /* toxav.h - * + * * Copyright (C) 2013-2015 Tox project All Rights Reserved. * * This file is part of Tox. @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with Tox. If not, see . - * + * */ #ifndef TOXAV_H @@ -31,37 +31,37 @@ extern "C" { #endif /** \page av Public audio/video API for Tox clients. - * + * * This API can handle multiple calls. Each call has its state, in very rare * occasions the library can change the state of the call without apps knowledge. - * + * */ /** \subsection events Events and callbacks * - * As in Core API, events are handled by callbacks. One callback can be - * registered per event. All events have a callback function type named + * As in Core API, events are handled by callbacks. One callback can be + * registered per event. All events have a callback function type named * `toxav_{event}_cb` and a function to register it named `toxav_callback_{event}`. - * Passing a NULL callback will result in no callback being registered for that - * event. Only one callback per event can be registered, so if a client needs - * multiple event listeners, it needs to implement the dispatch functionality - * itself. Unlike Core API, lack of some event handlers will cause the the - * library to drop calls before they are started. Hanging up call from a + * Passing a NULL callback will result in no callback being registered for that + * event. Only one callback per event can be registered, so if a client needs + * multiple event listeners, it needs to implement the dispatch functionality + * itself. Unlike Core API, lack of some event handlers will cause the the + * library to drop calls before they are started. Hanging up call from a * callback causes undefined behaviour. - * + * */ /** \subsection threading Threading implications * * Unlike the Core API, this API is fully thread-safe. The library will ensure - * the proper synchronization of parallel calls. - * + * the proper synchronization of parallel calls. + * * A common way to run ToxAV (multiple or single instance) is to have a thread, - * separate from tox instance thread, running a simple toxav_iterate loop, + * separate from tox instance thread, running a simple toxav_iterate loop, * sleeping for toxav_iteration_interval * milliseconds on each iteration. * * An important thing to note is that events are triggered from both tox and * toxav thread (see above). Audio and video receive frame events are triggered * from toxav thread while all the other events are triggered from tox thread. - * + * * Tox thread has priority with mutex mechanisms. Any api function can * fail if mutexes are held by tox thread in which case they will set SYNC * error code. @@ -81,9 +81,9 @@ typedef struct Tox Tox; * The ToxAV instance type. Each ToxAV instance can be bound to only one Tox * instance, and Tox instance can have only one ToxAV instance. One must make * sure to close ToxAV instance prior closing Tox instance otherwise undefined - * behaviour occurs. Upon closing of ToxAV instance, all active calls will be + * behaviour occurs. Upon closing of ToxAV instance, all active calls will be * forcibly terminated without notifying peers. - * + * */ #ifndef TOXAV_DEFINED #define TOXAV_DEFINED @@ -164,28 +164,28 @@ bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch) /******************************************************************************* - * + * * :: Creation and destruction * ******************************************************************************/ typedef enum TOXAV_ERR_NEW { - /** - * The function returned successfully. - */ - TOXAV_ERR_NEW_OK, - /** - * One of the arguments to the function was NULL when it was not expected. - */ - TOXAV_ERR_NEW_NULL, - /** - * Memory allocation failure while trying to allocate structures required for - * the A/V session. - */ - TOXAV_ERR_NEW_MALLOC, - /** - * Attempted to create a second session for the same Tox instance. - */ - TOXAV_ERR_NEW_MULTIPLE, + /** + * The function returned successfully. + */ + TOXAV_ERR_NEW_OK, + /** + * One of the arguments to the function was NULL when it was not expected. + */ + TOXAV_ERR_NEW_NULL, + /** + * Memory allocation failure while trying to allocate structures required for + * the A/V session. + */ + TOXAV_ERR_NEW_MALLOC, + /** + * Attempted to create a second session for the same Tox instance. + */ + TOXAV_ERR_NEW_MULTIPLE, } TOXAV_ERR_NEW; /** @@ -209,7 +209,7 @@ Tox *toxav_get_tox(const ToxAV *toxAV); /******************************************************************************* - * + * * :: A/V event loop * ******************************************************************************/ @@ -221,48 +221,48 @@ uint32_t toxav_iteration_interval(const ToxAV *toxAV); /** * Main loop for the session. This function needs to be called in intervals of - * toxav_iteration_interval() milliseconds. It is best called in the separate + * toxav_iteration_interval() milliseconds. It is best called in the separate * thread from tox_iterate. */ void toxav_iterate(ToxAV *toxAV); /******************************************************************************* - * + * * :: Call setup * ******************************************************************************/ typedef enum TOXAV_ERR_CALL { - /** - * The function returned successfully. - */ - TOXAV_ERR_CALL_OK, - /** - * A resource allocation error occurred while trying to create the structures - * required for the call. - */ - TOXAV_ERR_CALL_MALLOC, - /** - * Synchronization error occurred. - */ - TOXAV_ERR_CALL_SYNC, - /** - * The friend number did not designate a valid friend. - */ - TOXAV_ERR_CALL_FRIEND_NOT_FOUND, - /** - * The friend was valid, but not currently connected. - */ - TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED, - /** - * Attempted to call a friend while already in an audio or video call with - * them. - */ - TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL, - /** - * Audio or video bit rate is invalid. - */ - TOXAV_ERR_CALL_INVALID_BIT_RATE, + /** + * The function returned successfully. + */ + TOXAV_ERR_CALL_OK, + /** + * A resource allocation error occurred while trying to create the structures + * required for the call. + */ + TOXAV_ERR_CALL_MALLOC, + /** + * Synchronization error occurred. + */ + TOXAV_ERR_CALL_SYNC, + /** + * The friend number did not designate a valid friend. + */ + TOXAV_ERR_CALL_FRIEND_NOT_FOUND, + /** + * The friend was valid, but not currently connected. + */ + TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED, + /** + * Attempted to call a friend while already in an audio or video call with + * them. + */ + TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL, + /** + * Audio or video bit rate is invalid. + */ + TOXAV_ERR_CALL_INVALID_BIT_RATE, } TOXAV_ERR_CALL; /** @@ -270,7 +270,7 @@ typedef enum TOXAV_ERR_CALL { * * It is the client's responsibility to stop ringing after a certain timeout, * if such behaviour is desired. If the client does not stop ringing, the - * library will not stop until the friend is disconnected. Audio and video + * library will not stop until the friend is disconnected. Audio and video * receiving are both enabled by default. * * @param friend_number The friend number of the friend that should be called. @@ -284,7 +284,7 @@ bool toxav_call(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, /** * The function type for the call callback. - * + * * @param friend_number The friend number from which the call is incoming. * @param audio_enabled True if friend is sending audio. * @param video_enabled True if friend is sending video. @@ -299,33 +299,33 @@ typedef void toxav_call_cb(ToxAV *toxAV, uint32_t friend_number, bool audio_enab void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data); typedef enum TOXAV_ERR_ANSWER { - /** - * The function returned successfully. - */ - TOXAV_ERR_ANSWER_OK, - /** - * Synchronization error occurred. - */ - TOXAV_ERR_ANSWER_SYNC, - /** - * Failed to initialize codecs for call session. Note that codec initiation - * will fail if there is no receive callback registered for either audio or - * video. - */ - TOXAV_ERR_ANSWER_CODEC_INITIALIZATION, - /** - * The friend number did not designate a valid friend. - */ - TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND, - /** - * The friend was valid, but they are not currently trying to initiate a call. - * This is also returned if this client is already in a call with the friend. - */ - TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING, - /** - * Audio or video bit rate is invalid. - */ - TOXAV_ERR_ANSWER_INVALID_BIT_RATE, + /** + * The function returned successfully. + */ + TOXAV_ERR_ANSWER_OK, + /** + * Synchronization error occurred. + */ + TOXAV_ERR_ANSWER_SYNC, + /** + * Failed to initialize codecs for call session. Note that codec initiation + * will fail if there is no receive callback registered for either audio or + * video. + */ + TOXAV_ERR_ANSWER_CODEC_INITIALIZATION, + /** + * The friend number did not designate a valid friend. + */ + TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND, + /** + * The friend was valid, but they are not currently trying to initiate a call. + * This is also returned if this client is already in a call with the friend. + */ + TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING, + /** + * Audio or video bit rate is invalid. + */ + TOXAV_ERR_ANSWER_INVALID_BIT_RATE, } TOXAV_ERR_ANSWER; /** @@ -341,44 +341,45 @@ typedef enum TOXAV_ERR_ANSWER { * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable * video sending. */ -bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error); +bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, + TOXAV_ERR_ANSWER *error); /******************************************************************************* - * + * * :: Call state graph * ******************************************************************************/ enum TOXAV_FRIEND_CALL_STATE { - /** - * Set by the AV core if an error occurred on the remote end or if friend - * timed out. This is the final state after which no more state - * transitions can occur for the call. This call state will never be triggered - * in combination with other call states. - */ - TOXAV_FRIEND_CALL_STATE_ERROR = 1, - /** - * The call has finished. This is the final state after which no more state - * transitions can occur for the call. This call state will never be - * triggered in combination with other call states. - */ - TOXAV_FRIEND_CALL_STATE_FINISHED = 2, - /** - * The flag that marks that friend is sending audio. - */ - TOXAV_FRIEND_CALL_STATE_SENDING_A = 4, - /** - * The flag that marks that friend is sending video. - */ - TOXAV_FRIEND_CALL_STATE_SENDING_V = 8, - /** - * The flag that marks that friend is receiving audio. - */ - TOXAV_FRIEND_CALL_STATE_ACCEPTING_A = 16, - /** - * The flag that marks that friend is receiving video. - */ - TOXAV_FRIEND_CALL_STATE_ACCEPTING_V = 32, + /** + * Set by the AV core if an error occurred on the remote end or if friend + * timed out. This is the final state after which no more state + * transitions can occur for the call. This call state will never be triggered + * in combination with other call states. + */ + TOXAV_FRIEND_CALL_STATE_ERROR = 1, + /** + * The call has finished. This is the final state after which no more state + * transitions can occur for the call. This call state will never be + * triggered in combination with other call states. + */ + TOXAV_FRIEND_CALL_STATE_FINISHED = 2, + /** + * The flag that marks that friend is sending audio. + */ + TOXAV_FRIEND_CALL_STATE_SENDING_A = 4, + /** + * The flag that marks that friend is sending video. + */ + TOXAV_FRIEND_CALL_STATE_SENDING_V = 8, + /** + * The flag that marks that friend is receiving audio. + */ + TOXAV_FRIEND_CALL_STATE_ACCEPTING_A = 16, + /** + * The flag that marks that friend is receiving video. + */ + TOXAV_FRIEND_CALL_STATE_ACCEPTING_V = 32, }; /** @@ -399,70 +400,70 @@ typedef void toxav_call_state_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data); /******************************************************************************* - * + * * :: Call control * ******************************************************************************/ typedef enum TOXAV_CALL_CONTROL { - /** - * Resume a previously paused call. Only valid if the pause was caused by this - * client, if not, this control is ignored. Not valid before the call is accepted. - */ - TOXAV_CALL_CONTROL_RESUME, - /** - * Put a call on hold. Not valid before the call is accepted. - */ - TOXAV_CALL_CONTROL_PAUSE, - /** - * Reject a call if it was not answered, yet. Cancel a call after it was - * answered. - */ - TOXAV_CALL_CONTROL_CANCEL, - /** - * Request that the friend stops sending audio. Regardless of the friend's - * compliance, this will cause the audio_receive_frame event to stop being - * triggered on receiving an audio frame from the friend. - */ - TOXAV_CALL_CONTROL_MUTE_AUDIO, - /** - * Calling this control will notify client to start sending audio again. - */ - TOXAV_CALL_CONTROL_UNMUTE_AUDIO, - /** - * Request that the friend stops sending video. Regardless of the friend's - * compliance, this will cause the video_receive_frame event to stop being - * triggered on receiving a video frame from the friend. - */ - TOXAV_CALL_CONTROL_HIDE_VIDEO, - /** - * Calling this control will notify client to start sending video again. - */ - TOXAV_CALL_CONTROL_SHOW_VIDEO, + /** + * Resume a previously paused call. Only valid if the pause was caused by this + * client, if not, this control is ignored. Not valid before the call is accepted. + */ + TOXAV_CALL_CONTROL_RESUME, + /** + * Put a call on hold. Not valid before the call is accepted. + */ + TOXAV_CALL_CONTROL_PAUSE, + /** + * Reject a call if it was not answered, yet. Cancel a call after it was + * answered. + */ + TOXAV_CALL_CONTROL_CANCEL, + /** + * Request that the friend stops sending audio. Regardless of the friend's + * compliance, this will cause the audio_receive_frame event to stop being + * triggered on receiving an audio frame from the friend. + */ + TOXAV_CALL_CONTROL_MUTE_AUDIO, + /** + * Calling this control will notify client to start sending audio again. + */ + TOXAV_CALL_CONTROL_UNMUTE_AUDIO, + /** + * Request that the friend stops sending video. Regardless of the friend's + * compliance, this will cause the video_receive_frame event to stop being + * triggered on receiving a video frame from the friend. + */ + TOXAV_CALL_CONTROL_HIDE_VIDEO, + /** + * Calling this control will notify client to start sending video again. + */ + TOXAV_CALL_CONTROL_SHOW_VIDEO, } TOXAV_CALL_CONTROL; typedef enum TOXAV_ERR_CALL_CONTROL { - /** - * The function returned successfully. - */ - TOXAV_ERR_CALL_CONTROL_OK, - /** - * Synchronization error occurred. - */ - TOXAV_ERR_CALL_CONTROL_SYNC, - /** - * The friend_number passed did not designate a valid friend. - */ - TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND, - /** - * This client is currently not in a call with the friend. Before the call is - * answered, only CANCEL is a valid control. - */ - TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL, - /** - * Happens if user tried to pause an already paused call or if trying to - * resume a call that is not paused. - */ - TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION, + /** + * The function returned successfully. + */ + TOXAV_ERR_CALL_CONTROL_OK, + /** + * Synchronization error occurred. + */ + TOXAV_ERR_CALL_CONTROL_SYNC, + /** + * The friend_number passed did not designate a valid friend. + */ + TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND, + /** + * This client is currently not in a call with the friend. Before the call is + * answered, only CANCEL is a valid control. + */ + TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL, + /** + * Happens if user tried to pause an already paused call or if trying to + * resume a call that is not paused. + */ + TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION, } TOXAV_ERR_CALL_CONTROL; /** @@ -474,39 +475,40 @@ typedef enum TOXAV_ERR_CALL_CONTROL { * * @return true on success. */ -bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error); +bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, + TOXAV_ERR_CALL_CONTROL *error); /******************************************************************************* - * + * * :: Controlling bit rates * ******************************************************************************/ typedef enum TOXAV_ERR_BIT_RATE_SET { - /** - * The function returned successfully. - */ - TOXAV_ERR_BIT_RATE_SET_OK, - /** - * Synchronization error occurred. - */ - TOXAV_ERR_BIT_RATE_SET_SYNC, - /** - * The audio bit rate passed was not one of the supported values. - */ - TOXAV_ERR_BIT_RATE_SET_INVALID_AUDIO_BIT_RATE, - /** - * The video bit rate passed was not one of the supported values. - */ - TOXAV_ERR_BIT_RATE_SET_INVALID_VIDEO_BIT_RATE, - /** - * The friend_number passed did not designate a valid friend. - */ - TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND, - /** - * This client is currently not in a call with the friend. - */ - TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL, + /** + * The function returned successfully. + */ + TOXAV_ERR_BIT_RATE_SET_OK, + /** + * Synchronization error occurred. + */ + TOXAV_ERR_BIT_RATE_SET_SYNC, + /** + * The audio bit rate passed was not one of the supported values. + */ + TOXAV_ERR_BIT_RATE_SET_INVALID_AUDIO_BIT_RATE, + /** + * The video bit rate passed was not one of the supported values. + */ + TOXAV_ERR_BIT_RATE_SET_INVALID_VIDEO_BIT_RATE, + /** + * The friend_number passed did not designate a valid friend. + */ + TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND, + /** + * This client is currently not in a call with the friend. + */ + TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL, } TOXAV_ERR_BIT_RATE_SET; /** @@ -518,22 +520,23 @@ typedef enum TOXAV_ERR_BIT_RATE_SET { * audio sending. Set to -1 to leave unchanged. * @param video_bit_rate The new video bit rate in Kb/sec. Set to 0 to disable * video sending. Set to -1 to leave unchanged. - * + * */ bool toxav_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, int32_t audio_bit_rate, int32_t video_bit_rate, TOXAV_ERR_BIT_RATE_SET *error); /** * The function type for the bit_rate_status callback. The event is triggered - * when the network becomes too saturated for current bit rates at which + * when the network becomes too saturated for current bit rates at which * point core suggests new bit rates. - * + * * @param friend_number The friend number of the friend for which to set the * bit rate. * @param audio_bit_rate Suggested maximum audio bit rate in Kb/sec. * @param video_bit_rate Suggested maximum video bit rate in Kb/sec. */ -typedef void toxav_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, void *user_data); +typedef void toxav_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, + uint32_t video_bit_rate, void *user_data); /** * Set the callback for the `bit_rate_status` event. Pass NULL to unset. @@ -543,46 +546,46 @@ void toxav_callback_bit_rate_status(ToxAV *toxAV, toxav_bit_rate_status_cb *call /******************************************************************************* - * + * * :: A/V sending * ******************************************************************************/ typedef enum TOXAV_ERR_SEND_FRAME { - /** - * The function returned successfully. - */ - TOXAV_ERR_SEND_FRAME_OK, - /** - * In case of video, one of Y, U, or V was NULL. In case of audio, the samples - * data pointer was NULL. - */ - TOXAV_ERR_SEND_FRAME_NULL, - /** - * The friend_number passed did not designate a valid friend. - */ - TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND, - /** - * This client is currently not in a call with the friend. - */ - TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL, - /** - * Synchronization error occurred. - */ - TOXAV_ERR_SEND_FRAME_SYNC, - /** - * One of the frame parameters was invalid. E.g. the resolution may be too - * small or too large, or the audio sampling rate may be unsupported. - */ - TOXAV_ERR_SEND_FRAME_INVALID, - /** - * Either friend turned off audio or video receiving or we turned off sending - * for the said payload. - */ - TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED, - /** - * Failed to push frame through rtp interface. - */ - TOXAV_ERR_SEND_FRAME_RTP_FAILED, + /** + * The function returned successfully. + */ + TOXAV_ERR_SEND_FRAME_OK, + /** + * In case of video, one of Y, U, or V was NULL. In case of audio, the samples + * data pointer was NULL. + */ + TOXAV_ERR_SEND_FRAME_NULL, + /** + * The friend_number passed did not designate a valid friend. + */ + TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND, + /** + * This client is currently not in a call with the friend. + */ + TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL, + /** + * Synchronization error occurred. + */ + TOXAV_ERR_SEND_FRAME_SYNC, + /** + * One of the frame parameters was invalid. E.g. the resolution may be too + * small or too large, or the audio sampling rate may be unsupported. + */ + TOXAV_ERR_SEND_FRAME_INVALID, + /** + * Either friend turned off audio or video receiving or we turned off sending + * for the said payload. + */ + TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED, + /** + * Failed to push frame through rtp interface. + */ + TOXAV_ERR_SEND_FRAME_RTP_FAILED, } TOXAV_ERR_SEND_FRAME; /** @@ -605,7 +608,7 @@ typedef enum TOXAV_ERR_SEND_FRAME { * @param sampling_rate Audio sampling rate used in this frame. Valid sampling * rates are 8000, 12000, 16000, 24000, or 48000. */ -bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, +bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error); @@ -624,13 +627,13 @@ bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t * @param u U (Chroma) plane data. * @param v V (Chroma) plane data. */ -bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width, - uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, +bool toxav_video_send_frame(ToxAV *toxAV, 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); /******************************************************************************* - * + * * :: A/V receiving * ******************************************************************************/ @@ -638,7 +641,7 @@ bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width * The function type for the audio_receive_frame callback. The callback can be * called multiple times per single iteration depending on the amount of queued * frames in the buffer. The received format is the same as in send function. - * + * * @param friend_number The friend number of the friend who sent an audio frame. * @param pcm An array of audio samples (sample_count * channels elements). * @param sample_count The number of audio samples per channel in the PCM array. @@ -647,8 +650,8 @@ bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width * */ typedef void toxav_audio_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, - size_t sample_count, uint8_t channels, uint32_t sampling_rate, - void *user_data); + size_t sample_count, uint8_t channels, uint32_t sampling_rate, + void *user_data); /** * Set the callback for the `audio_receive_frame` event. Pass NULL to unset. @@ -662,24 +665,24 @@ void toxav_callback_audio_receive_frame(ToxAV *toxAV, toxav_audio_receive_frame_ * @param friend_number The friend number of the friend who sent a video frame. * @param width Width of the frame in pixels. * @param height Height of the frame in pixels. - * @param y - * @param u + * @param y + * @param u * @param v Plane data. * The size of plane data is derived from width and height where - * Y = MAX(width, abs(ystride)) * height, - * U = MAX(width/2, abs(ustride)) * (height/2) and + * Y = MAX(width, abs(ystride)) * height, + * U = MAX(width/2, abs(ustride)) * (height/2) and * V = MAX(width/2, abs(vstride)) * (height/2). * @param ystride * @param ustride * @param vstride Strides data. Strides represent padding for each plane * that may or may not be present. You must handle strides in - * your image processing code. Strides are negative if the + * your image processing code. Strides are negative if the * image is bottom-up hence why you MUST abs() it when * calculating plane buffer size. */ -typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width, - uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, - int32_t ystride, int32_t ustride, int32_t vstride, void *user_data); +typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width, + uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, + int32_t ystride, int32_t ustride, int32_t vstride, void *user_data); /** * Set the callback for the `video_receive_frame` event. Pass NULL to unset. @@ -700,7 +703,7 @@ void toxav_callback_video_receive_frame(ToxAV *toxAV, toxav_video_receive_frame_ * * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)). */ -int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void*, int, int, const int16_t *, unsigned int, uint8_t, +int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata); /* Join a AV group (you need to have been invited first.) @@ -714,7 +717,7 @@ int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void*, int, int, con * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)). */ int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length, - void (*audio_callback)(void*, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata); + void (*audio_callback)(void *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata); /* Send audio to the group chat. * diff --git a/toxav/video.c b/toxav/video.c index acc1852b..8a832201 100644 --- a/toxav/video.c +++ b/toxav/video.c @@ -207,43 +207,40 @@ int vc_queue_message(void *vcp, struct RTPMessage *msg) return 0; } -int vc_reconfigure_encoder(VCSession* vc, uint32_t bit_rate, uint16_t width, uint16_t height) +int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uint16_t height) { if (!vc) return -1; vpx_codec_enc_cfg_t cfg = *vc->encoder->config.enc; int rc; - + if (cfg.rc_target_bitrate == bit_rate && cfg.g_w == width && cfg.g_h == height) return 0; /* Nothing changed */ - if (cfg.g_w == width && cfg.g_h == height) - { + if (cfg.g_w == width && cfg.g_h == height) { /* Only bit rate changed */ cfg.rc_target_bitrate = bit_rate; - + rc = vpx_codec_enc_config_set(vc->encoder, &cfg); - + if (rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return -1; } - } - else - { + } else { /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support * reconfiguring encoder to use resolutions greater than initially set. */ - + LOGGER_DEBUG("Have to reinitialize vpx encoder on session %p", vc); - + cfg.rc_target_bitrate = bit_rate; cfg.g_w = width; cfg.g_h = height; vpx_codec_ctx_t new_c; - + rc = vpx_codec_enc_init(&new_c, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); if (rc != VPX_CODEC_OK) { @@ -258,7 +255,7 @@ int vc_reconfigure_encoder(VCSession* vc, uint32_t bit_rate, uint16_t width, uin vpx_codec_destroy(&new_c); return -1; } - + vpx_codec_destroy(vc->encoder); memcpy(vc->encoder, &new_c, sizeof(new_c)); } diff --git a/toxav/video.h b/toxav/video.h index 51f34318..fb836a35 100644 --- a/toxav/video.h +++ b/toxav/video.h @@ -58,7 +58,7 @@ typedef struct VCSession_s { pthread_mutex_t queue_mutex[1]; } VCSession; -VCSession *vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb* cb, void* cb_data); +VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data); void vc_kill(VCSession *vc); void vc_iterate(VCSession *vc); int vc_queue_message(void *vcp, struct RTPMessage *msg); diff --git a/toxcore/util.c b/toxcore/util.c index 81fa84c6..28d8721c 100644 --- a/toxcore/util.c +++ b/toxcore/util.c @@ -209,18 +209,19 @@ bool rb_empty(const RingBuffer *b) { return b->end == b->start; } -void* rb_write(RingBuffer *b, void *p) +void *rb_write(RingBuffer *b, void *p) { - void* rc = NULL; + void *rc = NULL; + if ((b->end + 1) % b->size == b->start) /* full */ rc = b->data[b->start]; - + b->data[b->end] = p; b->end = (b->end + 1) % b->size; - if (b->end == b->start) + if (b->end == b->start) b->start = (b->start + 1) % b->size; - + return rc; } bool rb_read(RingBuffer *b, void **p) @@ -229,7 +230,7 @@ bool rb_read(RingBuffer *b, void **p) *p = NULL; return false; } - + *p = b->data[b->start]; b->start = (b->start + 1) % b->size; return true; @@ -256,21 +257,22 @@ void rb_kill(RingBuffer *b) free(b); } } -uint16_t rb_size(const RingBuffer* b) -{ +uint16_t rb_size(const RingBuffer *b) +{ if (rb_empty(b)) return 0; - + return - b->end > b->start ? + b->end > b->start ? b->end - b->start : (b->size - b->start) + b->end; } -uint16_t rb_data(const RingBuffer* b, void** dest) +uint16_t rb_data(const RingBuffer *b, void **dest) { uint16_t i = 0; + for (; i < rb_size(b); i++) dest[i] = b->data[(b->start + i) % b->size]; - + return i; } diff --git a/toxcore/util.h b/toxcore/util.h index 7cf63178..bdbf7d3b 100644 --- a/toxcore/util.h +++ b/toxcore/util.h @@ -62,11 +62,11 @@ int create_recursive_mutex(pthread_mutex_t *mutex); typedef struct RingBuffer RingBuffer; bool rb_full(const RingBuffer *b); bool rb_empty(const RingBuffer *b); -void* rb_write(RingBuffer* b, void* p); -bool rb_read(RingBuffer* b, void** p); +void *rb_write(RingBuffer *b, void *p); +bool rb_read(RingBuffer *b, void **p); RingBuffer *rb_new(int size); void rb_kill(RingBuffer *b); uint16_t rb_size(const RingBuffer *b); -uint16_t rb_data(const RingBuffer* b, void** dest); +uint16_t rb_data(const RingBuffer *b, void **dest); #endif /* __UTIL_H__ */ diff --git a/toxdns/toxdns.c b/toxdns/toxdns.c index f7df5df3..1fbf4a00 100644 --- a/toxdns/toxdns.c +++ b/toxdns/toxdns.c @@ -44,7 +44,7 @@ uint8_t i = 0; \ } \ } \ } \ - + typedef struct { uint8_t temp_pk[crypto_box_PUBLICKEYBYTES]; uint8_t temp_sk[crypto_box_SECRETKEYBYTES];