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