diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc index 7a102579..1f0f6697 100644 --- a/auto_tests/Makefile.inc +++ b/auto_tests/Makefile.inc @@ -1,10 +1,9 @@ if BUILD_TESTS -#TESTS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test -#check_PROGRAMS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test - -TESTS = toxav_many_test -check_PROGRAMS = toxav_many_test +TESTS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test +#toxav_basic_test toxav_many_test +check_PROGRAMS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test +#toxav_basic_test toxav_many_test AUTOTEST_CFLAGS = \ $(LIBSODIUM_CFLAGS) \ @@ -20,61 +19,63 @@ AUTOTEST_LDADD = \ $(CHECK_LIBS) +#Tests don't work atm if BUILD_AV #TESTS += toxav_basic_test #check_PROGRAMS += toxav_basic_test -AUTOTEST_LDADD += libtoxav.la +#AUTOTEST_LDADD += libtoxav.la endif -#messenger_autotest_SOURCES = ../auto_tests/messenger_test.c +messenger_autotest_SOURCES = ../auto_tests/messenger_test.c -#messenger_autotest_CFLAGS = $(AUTOTEST_CFLAGS) +messenger_autotest_CFLAGS = $(AUTOTEST_CFLAGS) -#messenger_autotest_LDADD = $(AUTOTEST_LDADD) +messenger_autotest_LDADD = $(AUTOTEST_LDADD) -#crypto_test_SOURCES = ../auto_tests/crypto_test.c +crypto_test_SOURCES = ../auto_tests/crypto_test.c -#crypto_test_CFLAGS = $(AUTOTEST_CFLAGS) +crypto_test_CFLAGS = $(AUTOTEST_CFLAGS) -#crypto_test_LDADD = $(AUTOTEST_LDADD) +crypto_test_LDADD = $(AUTOTEST_LDADD) -#network_test_SOURCES = ../auto_tests/network_test.c +network_test_SOURCES = ../auto_tests/network_test.c -#network_test_CFLAGS = $(AUTOTEST_CFLAGS) +network_test_CFLAGS = $(AUTOTEST_CFLAGS) -#network_test_LDADD = $(AUTOTEST_LDADD) +network_test_LDADD = $(AUTOTEST_LDADD) -#assoc_test_SOURCES = ../auto_tests/assoc_test.c +assoc_test_SOURCES = ../auto_tests/assoc_test.c -#assoc_test_CFLAGS = $(AUTOTEST_CFLAGS) +assoc_test_CFLAGS = $(AUTOTEST_CFLAGS) -#assoc_test_LDADD = $(AUTOTEST_LDADD) +assoc_test_LDADD = $(AUTOTEST_LDADD) -#onion_test_SOURCES = ../auto_tests/onion_test.c +onion_test_SOURCES = ../auto_tests/onion_test.c -#onion_test_CFLAGS = $(AUTOTEST_CFLAGS) +onion_test_CFLAGS = $(AUTOTEST_CFLAGS) -#onion_test_LDADD = $(AUTOTEST_LDADD) +onion_test_LDADD = $(AUTOTEST_LDADD) -#TCP_test_SOURCES = ../auto_tests/TCP_test.c +TCP_test_SOURCES = ../auto_tests/TCP_test.c -#TCP_test_CFLAGS = $(AUTOTEST_CFLAGS) +TCP_test_CFLAGS = $(AUTOTEST_CFLAGS) -#TCP_test_LDADD = $(AUTOTEST_LDADD) +TCP_test_LDADD = $(AUTOTEST_LDADD) -#tox_test_SOURCES = ../auto_tests/tox_test.c +tox_test_SOURCES = ../auto_tests/tox_test.c -#tox_test_CFLAGS = $(AUTOTEST_CFLAGS) +tox_test_CFLAGS = $(AUTOTEST_CFLAGS) -#tox_test_LDADD = $(AUTOTEST_LDADD) +tox_test_LDADD = $(AUTOTEST_LDADD) +#Tests don't work atm if BUILD_AV #toxav_basic_test_SOURCES = ../auto_tests/toxav_basic_test.c @@ -83,11 +84,11 @@ if BUILD_AV #toxav_basic_test_LDADD = $(AUTOTEST_LDADD) -toxav_many_test_SOURCES = ../auto_tests/toxav_many_test.c +#toxav_many_test_SOURCES = ../auto_tests/toxav_many_test.c -toxav_many_test_CFLAGS = $(AUTOTEST_CFLAGS) +#toxav_many_test_CFLAGS = $(AUTOTEST_CFLAGS) -toxav_many_test_LDADD = $(AUTOTEST_LDADD) +#toxav_many_test_LDADD = $(AUTOTEST_LDADD) endif endif diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c index 048567bb..c8ebd497 100644 --- a/auto_tests/toxav_basic_test.c +++ b/auto_tests/toxav_basic_test.c @@ -46,6 +46,9 @@ typedef struct _Status { Party Bob; } Status; +/* My default settings */ +static ToxAvCodecSettings muhcaps; + void accept_friend_request(Tox *m, uint8_t *public_key, uint8_t *data, uint16_t length, void *userdata) { if (length == 7 && memcmp("gentoo", data, 7) == 0) { @@ -77,7 +80,7 @@ void callback_recv_starting ( uint32_t call_index, void *_arg ) /* Alice always sends invite */ printf("Call started on Alice side...\n"); cast->Alice.status = InCall; - toxav_prepare_transmission(cast->Alice.av, call_index, 1); + toxav_prepare_transmission(cast->Alice.av, call_index, &muhcaps, 1); } void callback_recv_ending ( uint32_t call_index, void *_arg ) { @@ -104,7 +107,7 @@ void callback_call_started ( uint32_t call_index, void *_arg ) /* Alice always sends invite */ printf("Call started on Bob side...\n"); cast->Bob.status = InCall; - toxav_prepare_transmission(cast->Bob.av, call_index, 1); + toxav_prepare_transmission(cast->Bob.av, call_index, &muhcaps, 1); } void callback_call_canceled ( uint32_t call_index, void *_arg ) { @@ -193,12 +196,12 @@ START_TEST(test_AV_flows) printf("All set after %llu seconds! Starting call...\n", time(NULL) - cur_time); - ToxAvCodecSettings muhcaps = av_DefaultSettings; + muhcaps = av_DefaultSettings; muhcaps.video_height = muhcaps.video_width = 128; Status status_control = { - {none, toxav_new(Alice, &muhcaps, 1), NULL}, - {none, toxav_new(Bob, &muhcaps, 1), NULL}, + {none, toxav_new(Alice, 1), NULL}, + {none, toxav_new(Bob, 1), NULL}, }; @@ -221,6 +224,9 @@ START_TEST(test_AV_flows) int16_t sample_payload[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t prepared_payload[1000]; + int payload_size; + vpx_image_t *sample_image = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, 128, 128, 1); memcpy(sample_image->planes[VPX_PLANE_Y], sample_payload, 10); @@ -237,15 +243,20 @@ START_TEST(test_AV_flows) */ CALL_AND_START_LOOP(TypeAudio, TypeAudio) { /* Both send */ - toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, sample_payload, 10); - toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, sample_payload, 10); + int payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, 1000, sample_payload, 120); + if (!( payload_size > 0 )) { /* FIXME: this will always fail */ + ck_assert_msg ( 0, "Failed to encode payload" ); + } + + toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size); + toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size); /* Both receive */ int16_t storage[10]; int recved; /* Payload from Bob */ - recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 10, storage); + recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 120, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ @@ -253,7 +264,7 @@ START_TEST(test_AV_flows) } /* Payload from Alice */ - recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 10, storage); + recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 120, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ @@ -276,10 +287,15 @@ START_TEST(test_AV_flows) */ CALL_AND_START_LOOP(TypeAudio, TypeVideo) { /* Both send */ - toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, sample_payload, 10); - - toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, sample_payload, 10); - toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); + int payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, 1000, sample_payload, 120); + if (!( payload_size > 0 )) { /* FIXME: this will always fail */ + ck_assert_msg ( 0, "Failed to encode payload" ); + } + + toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size); + + toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size); +// toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); /* Both receive */ int16_t storage[10]; @@ -287,7 +303,7 @@ START_TEST(test_AV_flows) int recved; /* Payload from Bob */ - recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 10, storage); + recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 120, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ @@ -295,19 +311,20 @@ START_TEST(test_AV_flows) } /* Video payload */ - toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage); - - if ( video_storage ) { - /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Bob is invalid");*/ - } +// toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage); +// +// if ( video_storage ) { +// /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || +// memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || +// memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Bob is invalid");*/ +// vpx_img_free(video_storage); +// } /* Payload from Alice */ - recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 10, storage); + recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 120, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ @@ -330,11 +347,16 @@ START_TEST(test_AV_flows) */ CALL_AND_START_LOOP(TypeVideo, TypeVideo) { /* Both send */ - toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, sample_payload, 10); - toxav_send_video(status_control.Alice.av, status_control.Alice.call_index, sample_image); - - toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, sample_payload, 10); - toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); + int payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, 1000, sample_payload, 120); + if (!( payload_size > 0 )) { /* FIXME: this will always fail */ + ck_assert_msg ( 0, "Failed to encode payload" ); + } + + toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size); +// toxav_send_video(status_control.Alice.av, status_control.Alice.call_index, sample_image); + + toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size); +// toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); /* Both receive */ int16_t storage[10]; @@ -342,7 +364,7 @@ START_TEST(test_AV_flows) int recved; /* Payload from Bob */ - recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 10, storage); + recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, 120, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ @@ -350,32 +372,34 @@ START_TEST(test_AV_flows) } /* Video payload */ - toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage); - - if ( video_storage ) { - /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Bob is invalid");*/ - } +// toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage); +// +// if ( video_storage ) { +// /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || +// memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || +// memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Bob is invalid");*/ +// vpx_img_free(video_storage); +// } /* Payload from Alice */ - recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 10, storage); + recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, 120, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ } /* Video payload */ - toxav_recv_video(status_control.Bob.av, status_control.Bob.call_index, &video_storage); - - if ( video_storage ) { - /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Alice is invalid");*/ - } +// toxav_recv_video(status_control.Bob.av, status_control.Bob.call_index, &video_storage); +// +// if ( video_storage ) { +// /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || +// memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || +// memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Alice is invalid");*/ +// vpx_img_free(video_storage); +// } if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ diff --git a/auto_tests/toxav_many_test.c b/auto_tests/toxav_many_test.c index 7ffa5138..77f3717e 100644 --- a/auto_tests/toxav_many_test.c +++ b/auto_tests/toxav_many_test.c @@ -131,12 +131,9 @@ void* in_thread_call (void* arg) int step = 0,running = 1; int call_idx; - int16_t sample_payload[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - vpx_image_t *sample_image = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, 128, 128, 1); - memcpy(sample_image->planes[VPX_PLANE_Y], sample_payload, 10); - memcpy(sample_image->planes[VPX_PLANE_U], sample_payload, 10); - memcpy(sample_image->planes[VPX_PLANE_V], sample_payload, 10); + int16_t sample_payload[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t prepared_payload[1000]; /* NOTE: CALLEE WILL ALWAHYS NEED CALL_IDX == 0 */ @@ -159,60 +156,43 @@ void* in_thread_call (void* arg) if (this_call->Caller.status == InCall) { /* I think this is okay */ call_print(call_idx, "Sending rtp ..."); + ToxAvCodecSettings cast = av_DefaultSettings; + c_sleep(1000); /* We have race condition here */ - toxav_prepare_transmission(this_call->Callee.av, 0, 1); - toxav_prepare_transmission(this_call->Caller.av, call_idx, 1); + toxav_prepare_transmission(this_call->Callee.av, 0, &cast, 1); + toxav_prepare_transmission(this_call->Caller.av, call_idx, &cast, 1); + + int payload_size = toxav_prepare_audio_frame(this_call->Caller.av, call_idx, prepared_payload, 1000, sample_payload, 120); + if (!( payload_size > 0 )) { + ck_assert_msg ( 0, "Failed to encode payload" ); + } while (time(NULL) - start < 10) { /* 10 seconds */ /* Both send */ - toxav_send_audio(this_call->Caller.av, call_idx, sample_payload, 10); - toxav_send_video(this_call->Caller.av, call_idx, sample_image); + toxav_send_audio(this_call->Caller.av, call_idx, prepared_payload, payload_size); - toxav_send_audio(this_call->Callee.av, 0, sample_payload, 10); - toxav_send_video(this_call->Callee.av, 0, sample_image); + toxav_send_audio(this_call->Callee.av, 0, prepared_payload, payload_size); + call_print(time(NULL) - start, "Blaaah"); /* Both receive */ - int16_t storage[10]; - vpx_image_t *video_storage; + int16_t storage[1000]; int recved; - /* Payload from CALLEE */ - recved = toxav_recv_audio(this_call->Caller.av, call_idx, 10, storage); - - if ( recved ) { - /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from CALLEE is invalid");*/ - memset(storage, 0, 10); - } - - /* Video payload */ - toxav_recv_video(this_call->Caller.av, call_idx, &video_storage); - - if ( video_storage ) { - /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || - * memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || - * memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from CALLEE is invalid");*/ - vpx_img_free(video_storage); - } - - - /* Payload from CALLER */ - recved = toxav_recv_audio(this_call->Callee.av, 0, 10, storage); + recved = toxav_recv_audio(this_call->Callee.av, 0, 120, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from CALLER is invalid");*/ } - /* Video payload */ - toxav_recv_video(this_call->Callee.av, 0, &video_storage); - - if ( video_storage ) { - /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || - * memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || - * memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from CALLER is invalid");*/ - vpx_img_free(video_storage); - } + /* Payload from CALLEE */ + recved = toxav_recv_audio(this_call->Caller.av, call_idx, 120, storage); + if ( recved ) { + /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from CALLEE is invalid");*/ + } + + //c_sleep(20); } step++; /* This terminates the loop */ @@ -247,6 +227,7 @@ void* in_thread_call (void* arg) START_TEST(test_AV_three_calls) +// void test_AV_three_calls() { long long unsigned int cur_time = time(NULL); Tox *bootstrap_node = tox_new(0); @@ -306,23 +287,20 @@ START_TEST(test_AV_three_calls) printf("All set after %llu seconds! Starting call...\n", time(NULL) - cur_time); - - ToxAvCodecSettings cast = av_DefaultSettings; - - ToxAv* uniqcallerav = toxav_new(caller, &cast, 3); + ToxAv* uniqcallerav = toxav_new(caller, 3); Status status_control = { 0, {none, uniqcallerav, 0}, - {none, toxav_new(callees[0], &cast, 1), 0}, + {none, toxav_new(callees[0], 1), 0}, 0, {none, uniqcallerav}, - {none, toxav_new(callees[1], &cast, 1), 1}, + {none, toxav_new(callees[1], 1), 1}, 0, {none, uniqcallerav}, - {none, toxav_new(callees[2], &cast, 1), 2} + {none, toxav_new(callees[2], 1), 2} }; @@ -404,4 +382,7 @@ int main(int argc, char *argv[]) return number_failed; +// test_AV_three_calls(); +// +// return 0; } \ No newline at end of file diff --git a/toxav/media.c b/toxav/media.c index 33d5d6b6..5700c2f2 100644 --- a/toxav/media.c +++ b/toxav/media.c @@ -36,8 +36,7 @@ #include "rtp.h" #include "media.h" - -int empty_queue(struct jitter_buffer *q) +int empty_queue(JitterBuffer *q) { while (q->size > 0) { rtp_free_msg(NULL, q->queue[q->front]); @@ -54,11 +53,11 @@ int empty_queue(struct jitter_buffer *q) return 0; } -struct jitter_buffer *create_queue(int capacity) +JitterBuffer *create_queue(int capacity) { - struct jitter_buffer *q; - q = calloc(sizeof(struct jitter_buffer), 1); - q->queue = calloc(sizeof(RTPMessage *), capacity); + JitterBuffer *q; + if ( !(q = calloc(sizeof(JitterBuffer), 1)) ) return NULL; + if (!(q->queue = calloc(sizeof(RTPMessage *), capacity))) return NULL; q->size = 0; q->capacity = capacity; q->front = 0; @@ -70,10 +69,20 @@ struct jitter_buffer *create_queue(int capacity) return q; } +void terminate_queue(JitterBuffer* q) +{ + int i; + for ( i = 0; i < q->capacity; i ++ ) { + rtp_free_msg(NULL, q->queue[i]); + } + free(q->queue); + free(q); +} + #define sequnum_older(sn_a, sn_b, ts_a, ts_b) (sn_a > sn_b || ts_a > ts_b) /* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */ -RTPMessage *dequeue(struct jitter_buffer *q, int *success) +RTPMessage *dequeue(JitterBuffer *q, int *success) { if (q->size == 0 || q->queue_ready == 0) { /* Empty queue */ q->queue_ready = 0; @@ -122,10 +131,10 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success) } -void queue(struct jitter_buffer* q, RTPMessage* pk) +void queue(JitterBuffer* q, RTPMessage* pk) { if (q->size == q->capacity) { /* Full, empty queue */ - LOGGER_DEBUG("Queue full, emptying..."); + LOGGER_DEBUG("Queue full s(%d) c(%d), emptying...", q->size, q->capacity); empty_queue(q); } @@ -257,7 +266,7 @@ CodecState *codec_init_session ( uint32_t audio_bitrate, uint32_t video_bitrate ) { CodecState *retu = calloc(sizeof(CodecState), 1); - assert(retu); + if(!retu) return NULL; retu->audio_bitrate = audio_bitrate; retu->audio_sample_rate = audio_sample_rate; @@ -275,6 +284,11 @@ CodecState *codec_init_session ( uint32_t audio_bitrate, retu->capabilities |= ( 0 == init_audio_encoder(retu, audio_channels) ) ? a_encoding : 0; retu->capabilities |= ( 0 == init_audio_decoder(retu, audio_channels) ) ? a_decoding : 0; + if ( retu->capabilities == 0 ) { /* everything failed */ + free (retu); + return NULL; + } + return retu; } diff --git a/toxav/media.h b/toxav/media.h index 68694664..a1193aae 100644 --- a/toxav/media.h +++ b/toxav/media.h @@ -69,7 +69,7 @@ typedef struct _CodecState { } CodecState; -struct jitter_buffer { +typedef struct _JitterBuffer { RTPMessage **queue; uint16_t capacity; uint16_t size; @@ -79,12 +79,12 @@ struct jitter_buffer { uint16_t current_id; uint32_t current_ts; uint8_t id_set; -}; +} JitterBuffer; -struct jitter_buffer *create_queue(int capacity); - -void queue(struct jitter_buffer *q, RTPMessage *pk); -RTPMessage *dequeue(struct jitter_buffer *q, int *success); +JitterBuffer *create_queue(int capacity); +void terminate_queue(JitterBuffer *q); +void queue(JitterBuffer *q, RTPMessage *pk); +RTPMessage *dequeue(JitterBuffer *q, int *success); CodecState *codec_init_session ( uint32_t audio_bitrate, diff --git a/toxav/rtp.c b/toxav/rtp.c index a404202b..1e6296b0 100755 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -754,11 +754,12 @@ RTPMessage *rtp_recv_msg ( RTPSession *session ) return NULL; } + pthread_mutex_lock(&session->mutex); + if ( session->queue_size == 0 ) { return NULL; } - pthread_mutex_lock(&session->mutex); RTPMessage *_retu = session->oldest_msg; @@ -768,8 +769,11 @@ RTPMessage *rtp_recv_msg ( RTPSession *session ) if ( !session->oldest_msg ) session->last_msg = NULL; + session->queue_size --; + pthread_mutex_unlock(&session->mutex); + return _retu; } diff --git a/toxav/toxav.c b/toxav/toxav.c index 0301c6b2..3a41754a 100755 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -25,17 +25,20 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ + +#define _GNU_SOURCE /* implicit declaration warning */ + #include "rtp.h" #include "media.h" #include "msi.h" +#include "toxav.h" #include "../toxcore/logger.h" + +#include #include #include -#include - -#include "toxav.h" /* Assume 60 fps*/ #define MAX_ENCODE_TIME_US ((1000 / 60) * 1000) @@ -45,27 +48,23 @@ static const uint8_t audio_index = 0, video_index = 1; -typedef struct _CallRTPSessions { - RTPSession *crtps[2]; /* Audio is first and video is second */ -} CallRTPSessions; +typedef struct _CallSpecific { + RTPSession *crtps[2]; /** Audio is first and video is second */ + CodecState *cs;/** Each call have its own encoders and decoders. + * You can, but don't have to, reuse encoders for + * multiple calls. If you choose to reuse encoders, + * make sure to also reuse encoded payload for every call. + * Decoders have to be unique for each call. FIXME: Now add refcounted encoders and + * reuse them really. + */ + JitterBuffer *j_buf; /** Jitter buffer for audio */ +} CallSpecific; -typedef enum { - ts_closing, - ts_running, - ts_closed - -} ThreadState; struct _ToxAv { Messenger *messenger; - MSISession *msi_session; /** Main msi session */ - - CallRTPSessions* rtp_sessions; - - struct jitter_buffer *j_buf; - CodecState *cs; - + CallSpecific* calls; /** Per-call params */ uint32_t max_calls; }; @@ -93,7 +92,7 @@ const ToxAvCodecSettings av_DefaultSettings = { * @return ToxAv* * @retval NULL On error. */ -ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings, uint32_t max_calls) +ToxAv *toxav_new( Tox* messenger, uint32_t max_calls) { ToxAv *av = calloc ( sizeof(ToxAv), 1); @@ -105,19 +104,9 @@ ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings, uint32_t m av->msi_session = msi_init_session(av->messenger, max_calls); av->msi_session->agent_handler = av; - av->rtp_sessions = calloc(sizeof(CallRTPSessions), max_calls); + av->calls = calloc(sizeof(CallSpecific), max_calls); av->max_calls = max_calls; - av->j_buf = create_queue(codec_settings->jbuf_capacity); - - av->cs = codec_init_session(codec_settings->audio_bitrate, - codec_settings->audio_frame_duration, - codec_settings->audio_sample_rate, - codec_settings->audio_channels, - codec_settings->video_width, - codec_settings->video_height, - codec_settings->video_bitrate); - return av; } @@ -133,19 +122,29 @@ void toxav_kill ( ToxAv *av ) int i = 0; for (; i < av->max_calls; i ++) { - if ( av->rtp_sessions[i].crtps[audio_index] ) { - rtp_terminate_session(av->rtp_sessions[i].crtps[audio_index], av->msi_session->messenger_handle); + if ( av->calls[i].crtps[audio_index] ) { + rtp_terminate_session(av->calls[i].crtps[audio_index], av->msi_session->messenger_handle); } - if ( av->rtp_sessions[i].crtps[video_index] ) { - rtp_terminate_session(av->rtp_sessions[i].crtps[video_index], av->msi_session->messenger_handle); + if ( av->calls[i].crtps[video_index] ) { + rtp_terminate_session(av->calls[i].crtps[video_index], av->msi_session->messenger_handle); + } + + av->calls[i].crtps[audio_index] = NULL; + av->calls[i].crtps[video_index] = NULL; + + if ( av->calls[i].j_buf ) { + terminate_queue(av->calls[i].j_buf); + av->calls[i].j_buf = NULL; + } + + if ( av->calls[i].cs ) { + codec_terminate_session(av->calls[i].cs); + av->calls[i].cs = NULL; } } - free(av->rtp_sessions); - - codec_terminate_session(av->cs); - + free(av->calls); free(av); } @@ -286,14 +285,16 @@ int toxav_stop_call ( ToxAv* av, uint32_t call_index ) * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_video ) +int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, ToxAvCodecSettings* codec_settings, int support_video ) { if ( !av->msi_session || av->msi_session->max_calls <= call_index || !av->msi_session->calls[call_index] ) { /*fprintf(stderr, "Error while starting audio RTP session: invalid call!\n");*/ return ErrorInternal; } - av->rtp_sessions[call_index].crtps[audio_index] = + CallSpecific* call = &av->calls[call_index]; + + call->crtps[audio_index] = rtp_init_session( type_audio, av->messenger, @@ -301,18 +302,17 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid av->msi_session->calls[call_index]->key_peer, av->msi_session->calls[call_index]->key_local, av->msi_session->calls[call_index]->nonce_peer, - av->msi_session->calls[call_index]->nonce_local - ); + av->msi_session->calls[call_index]->nonce_local); - if ( !av->rtp_sessions[call_index].crtps[audio_index] ) { + if ( !call->crtps[audio_index] ) { /*fprintf(stderr, "Error while starting audio RTP session!\n");*/ return ErrorStartingAudioRtp; } if ( support_video ) { - av->rtp_sessions[call_index].crtps[video_index] = + call->crtps[video_index] = rtp_init_session ( type_video, av->messenger, @@ -320,18 +320,26 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid av->msi_session->calls[call_index]->key_peer, av->msi_session->calls[call_index]->key_local, av->msi_session->calls[call_index]->nonce_peer, - av->msi_session->calls[call_index]->nonce_local - ); + av->msi_session->calls[call_index]->nonce_local); - if ( !av->rtp_sessions[call_index].crtps[video_index] ) { + if ( !call->crtps[video_index] ) { /*fprintf(stderr, "Error while starting video RTP session!\n");*/ return ErrorStartingVideoRtp; } } + if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) return ErrorInternal; - return ErrorNone; + call->cs = codec_init_session(codec_settings->audio_bitrate, + codec_settings->audio_frame_duration, + codec_settings->audio_sample_rate, + codec_settings->audio_channels, + codec_settings->video_width, + codec_settings->video_height, + codec_settings->video_bitrate); + + return call->cs ? ErrorNone : ErrorInternal; } /** @@ -344,19 +352,30 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid */ int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) { - if ( av->rtp_sessions[call_index].crtps[audio_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[audio_index], av->messenger) ) { + CallSpecific* call = &av->calls[call_index]; + + if ( call->crtps[audio_index] && -1 == rtp_terminate_session(call->crtps[audio_index], av->messenger) ) { /*fprintf(stderr, "Error while terminating audio RTP session!\n");*/ return ErrorTerminatingAudioRtp; } - if ( av->rtp_sessions[call_index].crtps[video_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[video_index], av->messenger) ) { + if ( call->crtps[video_index] && -1 == rtp_terminate_session(call->crtps[video_index], av->messenger) ) { /*fprintf(stderr, "Error while terminating video RTP session!\n");*/ return ErrorTerminatingVideoRtp; } - av->rtp_sessions[call_index].crtps[audio_index] = NULL; - av->rtp_sessions[call_index].crtps[video_index] = NULL; + call->crtps[audio_index] = NULL; + call->crtps[video_index] = NULL; + if ( call->j_buf ) { + terminate_queue(call->j_buf); + call->j_buf = NULL; + } + + if ( call->cs ) { + codec_terminate_session(call->cs); + call->cs = NULL; + } return ErrorNone; } @@ -375,8 +394,8 @@ int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) */ inline__ int toxav_send_rtp_payload ( ToxAv *av, uint32_t call_index, ToxAvCallType type, const uint8_t *payload, uint16_t length ) { - if ( av->rtp_sessions[call_index].crtps[type - TypeAudio] ) - return rtp_send_msg ( av->rtp_sessions[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, payload, length ); + if ( av->calls[call_index].crtps[type - TypeAudio] ) + return rtp_send_msg ( av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, payload, length ); else return -1; } @@ -394,27 +413,29 @@ inline__ int toxav_recv_rtp_payload ( ToxAv *av, uint32_t call_index, ToxAvCallT { if ( !dest ) return ErrorInternal; - if ( !av->rtp_sessions[call_index].crtps[type - TypeAudio] ) return ErrorNoRtpSession; + CallSpecific* call = &av->calls[call_index]; + + if ( !call->crtps[type - TypeAudio] ) return ErrorNoRtpSession; RTPMessage *message; if ( type == TypeAudio ) { do { - message = rtp_recv_msg(av->rtp_sessions[call_index].crtps[audio_index]); + message = rtp_recv_msg(call->crtps[audio_index]); if (message) { /* push the packet into the queue */ - queue(av->j_buf, message); + queue(call->j_buf, message); } } while (message); int success = 0; - message = dequeue(av->j_buf, &success); + message = dequeue(call->j_buf, &success); if ( success == 2) return ErrorAudioPacketLost; } else { - message = rtp_recv_msg(av->rtp_sessions[call_index].crtps[video_index]); + message = rtp_recv_msg(call->crtps[video_index]); } if ( message ) { @@ -446,11 +467,12 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = 0; int rc; + CallSpecific* call = &av->calls[call_index]; do { recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); - if (recved_size > 0 && ( rc = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) { + if (recved_size > 0 && ( rc = vpx_codec_decode(&call->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) { /*fprintf(stderr, "Error decoding video: %s\n", vpx_codec_err_to_string(rc));*/ return ErrorInternal; } @@ -459,12 +481,10 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou vpx_codec_iter_t iter = NULL; vpx_image_t *img; - img = vpx_codec_get_frame(&av->cs->v_decoder, &iter); + img = vpx_codec_get_frame(&call->cs->v_decoder, &iter); *output = img; return 0; - /* Yeah, i set output to be NULL if nothing received - */ } /** @@ -476,60 +496,47 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou * @retval 0 Success. * @retval ToxAvError On error. */ -inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *input) +inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, const uint8_t* frame, int frame_size) { - int rc = vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); - if ( rc != VPX_CODEC_OK) { - /*fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));*/ - return ErrorInternal; - } - - ++av->cs->frame_counter; - - vpx_codec_iter_t iter = NULL; - const vpx_codec_cx_pkt_t *pkt; - int sent = 0; - - while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { - if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { - if (toxav_send_rtp_payload(av, call_index, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1) - ++sent; - } - } - - if (sent > 0) - return ErrorNone; - - return ErrorInternal; + return toxav_send_rtp_payload(av, call_index, TypeVideo, frame, frame_size); } -int toxav_prepare_video_frame(ToxAv* av, uint8_t* dest, int dest_max, vpx_image_t* input) +/** + * @brief Encode video frame + * + * @param av Handler + * @param dest Where to + * @param dest_max Max size + * @param input What to encode + * @return int + * @retval ToxAvError On error. + * @retval >0 On success + */ +inline__ int toxav_prepare_video_frame(ToxAv* av, uint32_t call_index, uint8_t* dest, int dest_max, vpx_image_t* input) { - int rc = vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); + CallSpecific* call = &av->calls[call_index]; + + int rc = vpx_codec_encode(&call->cs->v_encoder, input, call->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); if ( rc != VPX_CODEC_OK) { - /*fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));*/ + fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc)); return ErrorInternal; } - ++av->cs->frame_counter; + ++call->cs->frame_counter; vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; - int counted = 0, copied = 0; + int copied = 0; - while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { - if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { - + while ( (pkt = vpx_codec_get_cx_data(&call->cs->v_encoder, &iter)) ) { + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { if ( copied + pkt->data.frame.sz > dest_max ) return ErrorPacketTooLarge; mempcpy(dest + copied, pkt->data.frame.buf, pkt->data.frame.sz); - - if (toxav_send_rtp_payload(av, call_index, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1) - ++counted; + copied += pkt->data.frame.sz; } } - if (counted > 0) - return ErrorNone; + return copied; } /** @@ -547,21 +554,28 @@ int toxav_prepare_video_frame(ToxAv* av, uint8_t* dest, int dest_max, vpx_image_ inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size, int16_t *dest ) { if ( !dest ) return ErrorInternal; + + CallSpecific* call = &av->calls[call_index]; uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet); if ( recved_size == ErrorAudioPacketLost ) { - int dec_size = opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); + int dec_size = opus_decode(call->cs->audio_decoder, NULL, 0, dest, frame_size, 1); - if ( dec_size != OPUS_OK ) return ErrorInternal; + if ( dec_size != OPUS_OK ) + return ErrorInternal; + else + return dec_size; } else if ( recved_size ) { - int dec_size = opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); - - if ( dec_size != OPUS_OK ) return ErrorInternal; + int dec_size = opus_decode(call->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); + if ( dec_size != OPUS_OK ) + return ErrorInternal; + else + return dec_size; } else { return 0; /* Nothing received */ } @@ -578,7 +592,7 @@ inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size, * @retval 0 Success. * @retval ToxAvError On error. */ -inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *frame, int frame_size) +inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const uint8_t *frame, int frame_size) { return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size); } @@ -595,13 +609,14 @@ inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *f * @retval ToxAvError On error. * @retval >0 On success */ -int toxav_prepare_audio_frame ( ToxAv* av, int16_t* dest, int dest_max, const int16_t* frame, int frame_size) +inline__ int toxav_prepare_audio_frame ( ToxAv* av, uint32_t call_index, uint8_t* dest, int dest_max, const int16_t* frame, int frame_size) { - int32_t rc = opus_encode(av->cs->audio_encoder, frame, frame_size, dest, dest_max); + int32_t rc = opus_encode(av->calls[call_index].cs->audio_encoder, frame, frame_size, dest, dest_max); - if (rc <= 0) + if (rc < 0) { + fprintf(stderr, "Failed to encode payload: %s\n", opus_strerror(rc)); return ErrorInternal; - + } return rc; } @@ -650,9 +665,9 @@ int toxav_get_peer_id ( ToxAv* av, uint32_t call_index, int peer ) * @retval 1 Yes. * @retval 0 No. */ -inline__ int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capability ) +inline__ int toxav_capability_supported ( ToxAv* av, uint32_t call_index, ToxAvCapabilities capability ) { - return av->cs->capabilities & (Capabilities) capability; + return av->calls[call_index].cs->capabilities & (Capabilities) capability; } /** @@ -665,7 +680,7 @@ inline__ int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capabilit */ void toxav_set_audio_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) { - rtp_queue_adjust_limit(av->rtp_sessions[call_index].crtps[audio_index], limit); + rtp_queue_adjust_limit(av->calls[call_index].crtps[audio_index], limit); } /** @@ -678,5 +693,5 @@ void toxav_set_audio_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) */ void toxav_set_video_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) { - rtp_queue_adjust_limit(av->rtp_sessions[call_index].crtps[video_index], limit); + rtp_queue_adjust_limit(av->calls[call_index].crtps[video_index], limit); } diff --git a/toxav/toxav.h b/toxav/toxav.h index 5a8e8f56..6dac966b 100755 --- a/toxav/toxav.h +++ b/toxav/toxav.h @@ -133,7 +133,7 @@ extern const ToxAvCodecSettings av_DefaultSettings; * @return ToxAv* * @retval NULL On error. */ -ToxAv *toxav_new(Tox *messenger, ToxAvCodecSettings* codec_settings, uint32_t max_calls); +ToxAv *toxav_new(Tox *messenger, uint32_t max_calls); /** * @brief Remove A/V session. @@ -228,7 +228,7 @@ int toxav_stop_call(ToxAv *av, uint32_t call_index); * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_prepare_transmission(ToxAv* av, uint32_t call_index, int support_video); +int toxav_prepare_transmission(ToxAv* av, uint32_t call_index, ToxAvCodecSettings* codec_settings, int support_video); /** * @brief Call this at the end of the transmission. @@ -269,12 +269,13 @@ int toxav_recv_audio( ToxAv* av, uint32_t call_index, int frame_size, int16_t* d * @brief Encode and send video packet. * * @param av Handler. - * @param input The packet. + * @param frame The encoded frame. + * @param frame_size The size of the encoded frame. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input); +int toxav_send_video ( ToxAv* av, uint32_t call_index, const uint8_t* frame, int frame_size); /** * @brief Send audio frame. @@ -287,9 +288,20 @@ int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input); * @retval 0 Success. * @retval ToxAvError On error. */ -int toxav_send_audio ( ToxAv* av, uint32_t call_index, const int16_t* frame, int frame_size); +int toxav_send_audio ( ToxAv* av, uint32_t call_index, const uint8_t* frame, int frame_size); -int toxav_prepare_video_frame ( ToxAv* av, uint8_t* dest, int dest_max, vpx_image_t* input ); +/** + * @brief Encode video frame + * + * @param av Handler + * @param dest Where to + * @param dest_max Max size + * @param input What to encode + * @return int + * @retval ToxAvError On error. + * @retval >0 On success + */ +int toxav_prepare_video_frame ( ToxAv* av, uint32_t call_index, uint8_t* dest, int dest_max, vpx_image_t* input ); /** * @brief Encode audio frame @@ -303,7 +315,7 @@ int toxav_prepare_video_frame ( ToxAv* av, uint8_t* dest, int dest_max, vpx_imag * @retval ToxAvError On error. * @retval >0 On success */ -int toxav_prepare_audio_frame ( ToxAv* av, int16_t* dest, int dest_max, const int16_t* frame, int frame_size); +int toxav_prepare_audio_frame ( ToxAv* av, uint32_t call_index, uint8_t* dest, int dest_max, const int16_t* frame, int frame_size); /** * @brief Get peer transmission type. It can either be audio or video. @@ -334,7 +346,7 @@ int toxav_get_peer_id ( ToxAv* av, uint32_t call_index, int peer ); * @retval 1 Yes. * @retval 0 No. */ -int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capability ); +int toxav_capability_supported ( ToxAv* av, uint32_t call_index, ToxAvCapabilities capability ); /** * @brief Set queue limit diff --git a/toxcore/logger.h b/toxcore/logger.h index 6c65850e..abef4b84 100644 --- a/toxcore/logger.h +++ b/toxcore/logger.h @@ -25,10 +25,10 @@ #ifndef __TOXLOGGER #define __TOXLOGGER +#include // #define LOGGING #ifdef LOGGING -#include typedef enum _LoggerLevel {