summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
Diffstat (limited to 'toxav')
-rw-r--r--toxav/audio.c10
-rw-r--r--toxav/bwcontroler.c62
-rw-r--r--toxav/msi.c79
-rw-r--r--toxav/rtp.c27
-rw-r--r--toxav/toxav.c57
-rw-r--r--toxav/toxav.h541
-rw-r--r--toxav/video.c23
-rw-r--r--toxav/video.h2
8 files changed, 409 insertions, 392 deletions
diff --git a/toxav/audio.c b/toxav/audio.c
index 4f9d3562..ad543502 100644
--- a/toxav/audio.c
+++ b/toxav/audio.c
@@ -76,11 +76,11 @@ ACSession *ac_new(ToxAV *av, uint32_t friend_number, toxav_audio_receive_frame_c
76 76
77 if (ac->encoder == NULL) 77 if (ac->encoder == NULL)
78 goto DECODER_CLEANUP; 78 goto DECODER_CLEANUP;
79 79
80 ac->le_bit_rate = 48000; 80 ac->le_bit_rate = 48000;
81 ac->le_sample_rate = 48000; 81 ac->le_sample_rate = 48000;
82 ac->le_channel_count = 2; 82 ac->le_channel_count = 2;
83 83
84 ac->ld_channel_count = 2; 84 ac->ld_channel_count = 2;
85 ac->ld_sample_rate = 48000; 85 ac->ld_sample_rate = 48000;
86 ac->ldrts = 0; /* Make it possible to reconfigure straight away */ 86 ac->ldrts = 0; /* Make it possible to reconfigure straight away */
@@ -126,7 +126,7 @@ void ac_iterate(ACSession *ac)
126 return; 126 return;
127 127
128 /* TODO fix this and jitter buffering */ 128 /* TODO fix this and jitter buffering */
129 129
130 /* Enough space for the maximum frame size (120 ms 48 KHz stereo audio) */ 130 /* Enough space for the maximum frame size (120 ms 48 KHz stereo audio) */
131 int16_t tmp[5760 * 2]; 131 int16_t tmp[5760 * 2];
132 132
@@ -221,9 +221,9 @@ int ac_queue_message(void *acp, struct RTPMessage *msg)
221} 221}
222int ac_reconfigure_encoder(ACSession *ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels) 222int ac_reconfigure_encoder(ACSession *ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels)
223{ 223{
224 if (!ac || !reconfigure_audio_encoder(&ac->encoder, bit_rate, 224 if (!ac || !reconfigure_audio_encoder(&ac->encoder, bit_rate,
225 sampling_rate, channels, 225 sampling_rate, channels,
226 &ac->le_bit_rate, 226 &ac->le_bit_rate,
227 &ac->le_sample_rate, 227 &ac->le_sample_rate,
228 &ac->le_channel_count)) 228 &ac->le_channel_count))
229 return -1; 229 return -1;
diff --git a/toxav/bwcontroler.c b/toxav/bwcontroler.c
index 2530e7fd..9dd15c93 100644
--- a/toxav/bwcontroler.c
+++ b/toxav/bwcontroler.c
@@ -34,7 +34,7 @@
34#define BWC_AVG_PKT_COUNT 20 34#define BWC_AVG_PKT_COUNT 20
35 35
36/** 36/**
37 * 37 *
38 */ 38 */
39 39
40struct BWControler_s { 40struct BWControler_s {
@@ -77,10 +77,11 @@ BWControler *bwc_new(Messenger *m, uint32_t friendnumber,
77 77
78 /* Fill with zeros */ 78 /* Fill with zeros */
79 int i = 0; 79 int i = 0;
80
80 for (; i < BWC_AVG_PKT_COUNT; i ++) 81 for (; i < BWC_AVG_PKT_COUNT; i ++)
81 rb_write(retu->rcvpkt.rb, retu->rcvpkt.rb_s + i); 82 rb_write(retu->rcvpkt.rb, retu->rcvpkt.rb_s + i);
82 83
83 m_callback_rtp_packet(m, friendnumber, BWC_PACKET_ID, bwc_handle_data, retu); 84 m_callback_rtp_packet(m, friendnumber, BWC_PACKET_ID, bwc_handle_data, retu);
84 85
85 return retu; 86 return retu;
86} 87}
@@ -88,19 +89,19 @@ void bwc_kill(BWControler *bwc)
88{ 89{
89 if (!bwc) 90 if (!bwc)
90 return; 91 return;
91 92
92 m_callback_rtp_packet(bwc->m, bwc->friend_number, BWC_PACKET_ID, NULL, NULL); 93 m_callback_rtp_packet(bwc->m, bwc->friend_number, BWC_PACKET_ID, NULL, NULL);
93 94
94 rb_kill(bwc->rcvpkt.rb); 95 rb_kill(bwc->rcvpkt.rb);
95 free(bwc); 96 free(bwc);
96} 97}
97void bwc_feed_avg(BWControler* bwc, uint32_t bytes) 98void bwc_feed_avg(BWControler *bwc, uint32_t bytes)
98{ 99{
99 uint32_t *p; 100 uint32_t *p;
100 101
101 rb_read(bwc->rcvpkt.rb, (void**) &p); 102 rb_read(bwc->rcvpkt.rb, (void **) &p);
102 rb_write(bwc->rcvpkt.rb, p); 103 rb_write(bwc->rcvpkt.rb, p);
103 104
104 *p = bytes; 105 *p = bytes;
105} 106}
106void bwc_add_lost(BWControler *bwc, uint32_t bytes) 107void bwc_add_lost(BWControler *bwc, uint32_t bytes)
@@ -109,21 +110,22 @@ void bwc_add_lost(BWControler *bwc, uint32_t bytes)
109 return; 110 return;
110 111
111 if (!bytes) { 112 if (!bytes) {
112 uint32_t* t_avg[BWC_AVG_PKT_COUNT], c = 1; 113 uint32_t *t_avg[BWC_AVG_PKT_COUNT], c = 1;
113 114
114 rb_data(bwc->rcvpkt.rb, (void**) t_avg); 115 rb_data(bwc->rcvpkt.rb, (void **) t_avg);
115 116
116 int i = 0; 117 int i = 0;
118
117 for (; i < BWC_AVG_PKT_COUNT; i ++) { 119 for (; i < BWC_AVG_PKT_COUNT; i ++) {
118 bytes += *(t_avg[i]); 120 bytes += *(t_avg[i]);
119 121
120 if (*(t_avg[i])) 122 if (*(t_avg[i]))
121 c++; 123 c++;
122 } 124 }
123 125
124 bytes /= c; 126 bytes /= c;
125 } 127 }
126 128
127 bwc->cycle.lost += bytes; 129 bwc->cycle.lost += bytes;
128 send_update(bwc); 130 send_update(bwc);
129} 131}
@@ -131,7 +133,7 @@ void bwc_add_recv(BWControler *bwc, uint32_t bytes)
131{ 133{
132 if (!bwc || !bytes) 134 if (!bwc || !bytes)
133 return; 135 return;
134 136
135 bwc->cycle.recv += bytes; 137 bwc->cycle.recv += bytes;
136 send_update(bwc); 138 send_update(bwc);
137} 139}
@@ -145,21 +147,19 @@ struct BWCMessage {
145void send_update(BWControler *bwc) 147void send_update(BWControler *bwc)
146{ 148{
147 if (current_time_monotonic() - bwc->cycle.lfu > BWC_REFRESH_INTERVAL_MS) { 149 if (current_time_monotonic() - bwc->cycle.lfu > BWC_REFRESH_INTERVAL_MS) {
148 150
149 bwc->cycle.lost /= 10; 151 bwc->cycle.lost /= 10;
150 bwc->cycle.recv /= 10; 152 bwc->cycle.recv /= 10;
151 bwc->cycle.lfu = current_time_monotonic(); 153 bwc->cycle.lfu = current_time_monotonic();
152 } 154 } else if (current_time_monotonic() - bwc->cycle.lsu > BWC_SEND_INTERVAL_MS) {
153 else if (current_time_monotonic() - bwc->cycle.lsu > BWC_SEND_INTERVAL_MS) { 155
154 156 if (bwc->cycle.lost) {
155 if (bwc->cycle.lost)
156 {
157 LOGGER_DEBUG ("%p Sent update rcv: %u lost: %u", 157 LOGGER_DEBUG ("%p Sent update rcv: %u lost: %u",
158 bwc, bwc->cycle.recv, bwc->cycle.lost); 158 bwc, bwc->cycle.recv, bwc->cycle.lost);
159 159
160 uint8_t p_msg[sizeof(struct BWCMessage) + 1]; 160 uint8_t p_msg[sizeof(struct BWCMessage) + 1];
161 struct BWCMessage* b_msg = (struct BWCMessage*)(p_msg + 1); 161 struct BWCMessage *b_msg = (struct BWCMessage *)(p_msg + 1);
162 162
163 p_msg[0] = BWC_PACKET_ID; 163 p_msg[0] = BWC_PACKET_ID;
164 b_msg->lost = htonl(bwc->cycle.lost); 164 b_msg->lost = htonl(bwc->cycle.lost);
165 b_msg->recv = htonl(bwc->cycle.recv); 165 b_msg->recv = htonl(bwc->cycle.recv);
@@ -167,27 +167,27 @@ void send_update(BWControler *bwc)
167 if (-1 == send_custom_lossy_packet(bwc->m, bwc->friend_number, p_msg, sizeof(p_msg))) 167 if (-1 == send_custom_lossy_packet(bwc->m, bwc->friend_number, p_msg, sizeof(p_msg)))
168 LOGGER_WARNING("BWC send failed (len: %d)! std error: %s", sizeof(p_msg), strerror(errno)); 168 LOGGER_WARNING("BWC send failed (len: %d)! std error: %s", sizeof(p_msg), strerror(errno));
169 } 169 }
170 170
171 bwc->cycle.lsu = current_time_monotonic(); 171 bwc->cycle.lsu = current_time_monotonic();
172 } 172 }
173} 173}
174int on_update (BWControler *bwc, struct BWCMessage *msg) 174int on_update (BWControler *bwc, struct BWCMessage *msg)
175{ 175{
176 LOGGER_DEBUG ("%p Got update from peer", bwc); 176 LOGGER_DEBUG ("%p Got update from peer", bwc);
177 177
178 /* Peer must respect time boundary */ 178 /* Peer must respect time boundary */
179 if (current_time_monotonic() < bwc->cycle.lru + BWC_SEND_INTERVAL_MS) { 179 if (current_time_monotonic() < bwc->cycle.lru + BWC_SEND_INTERVAL_MS) {
180 LOGGER_DEBUG("%p Rejecting extra update", bwc); 180 LOGGER_DEBUG("%p Rejecting extra update", bwc);
181 return -1; 181 return -1;
182 } 182 }
183 183
184 bwc->cycle.lru = current_time_monotonic(); 184 bwc->cycle.lru = current_time_monotonic();
185 185
186 msg->recv = ntohl(msg->recv); 186 msg->recv = ntohl(msg->recv);
187 msg->lost = ntohl(msg->lost); 187 msg->lost = ntohl(msg->lost);
188 188
189 LOGGER_DEBUG ("recved: %u lost: %u", msg->recv, msg->lost); 189 LOGGER_DEBUG ("recved: %u lost: %u", msg->recv, msg->lost);
190 190
191 if (msg->lost && bwc->mcb) 191 if (msg->lost && bwc->mcb)
192 bwc->mcb(bwc, bwc->friend_number, 192 bwc->mcb(bwc, bwc->friend_number,
193 ((float) (msg->lost) / (msg->recv + msg->lost)), 193 ((float) (msg->lost) / (msg->recv + msg->lost)),
@@ -195,7 +195,7 @@ int on_update (BWControler *bwc, struct BWCMessage *msg)
195 195
196 return 0; 196 return 0;
197} 197}
198int bwc_handle_data(Messenger* m, uint32_t friendnumber, const uint8_t* data, uint16_t length, void* object) 198int bwc_handle_data(Messenger *m, uint32_t friendnumber, const uint8_t *data, uint16_t length, void *object)
199{ 199{
200 if (length - 1 != sizeof(struct BWCMessage)) 200 if (length - 1 != sizeof(struct BWCMessage))
201 return -1; 201 return -1;
diff --git a/toxav/msi.c b/toxav/msi.c
index 7ad39a54..c08c0135 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -99,7 +99,7 @@ void msi_register_callback (MSISession *session, msi_action_cb *callback, MSICal
99{ 99{
100 if (!session) 100 if (!session)
101 return; 101 return;
102 102
103 pthread_mutex_lock(session->mutex); 103 pthread_mutex_lock(session->mutex);
104 session->callbacks[id] = callback; 104 session->callbacks[id] = callback;
105 pthread_mutex_unlock(session->mutex); 105 pthread_mutex_unlock(session->mutex);
@@ -142,7 +142,7 @@ int msi_kill (MSISession *session)
142 } 142 }
143 143
144 m_callback_msi_packet((struct Messenger *) session->messenger, NULL, NULL); 144 m_callback_msi_packet((struct Messenger *) session->messenger, NULL, NULL);
145 145
146 if (pthread_mutex_trylock(session->mutex) != 0) { 146 if (pthread_mutex_trylock(session->mutex) != 0) {
147 LOGGER_ERROR ("Failed to aquire lock on msi mutex"); 147 LOGGER_ERROR ("Failed to aquire lock on msi mutex");
148 return -1; 148 return -1;
@@ -171,7 +171,7 @@ int msi_invite (MSISession *session, MSICall **call, uint32_t friend_number, uin
171{ 171{
172 if (!session) 172 if (!session)
173 return -1; 173 return -1;
174 174
175 LOGGER_DEBUG("Session: %p Inviting friend: %u", session, friend_number); 175 LOGGER_DEBUG("Session: %p Inviting friend: %u", session, friend_number);
176 176
177 if (pthread_mutex_trylock(session->mutex) != 0) { 177 if (pthread_mutex_trylock(session->mutex) != 0) {
@@ -212,11 +212,11 @@ int msi_hangup (MSICall *call)
212{ 212{
213 if (!call || !call->session) 213 if (!call || !call->session)
214 return -1; 214 return -1;
215 215
216 LOGGER_DEBUG("Session: %p Hanging up call with friend: %u", call->session, call->friend_number); 216 LOGGER_DEBUG("Session: %p Hanging up call with friend: %u", call->session, call->friend_number);
217 217
218 MSISession *session = call->session; 218 MSISession *session = call->session;
219 219
220 if (pthread_mutex_trylock(session->mutex) != 0) { 220 if (pthread_mutex_trylock(session->mutex) != 0) {
221 LOGGER_ERROR ("Failed to aquire lock on msi mutex"); 221 LOGGER_ERROR ("Failed to aquire lock on msi mutex");
222 return -1; 222 return -1;
@@ -278,7 +278,7 @@ int msi_change_capabilities(MSICall *call, uint8_t capabilities)
278{ 278{
279 if (!call || !call->session) 279 if (!call || !call->session)
280 return -1; 280 return -1;
281 281
282 LOGGER_DEBUG("Session: %p Trying to change capabilities to friend %u", call->session, call->friend_number); 282 LOGGER_DEBUG("Session: %p Trying to change capabilities to friend %u", call->session, call->friend_number);
283 283
284 MSISession *session = call->session; 284 MSISession *session = call->session;
@@ -619,19 +619,18 @@ void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void *
619 break; 619 break;
620 } 620 }
621} 621}
622void handle_init (MSICall* call, const MSIMessage* msg) 622void handle_init (MSICall *call, const MSIMessage *msg)
623{ 623{
624 assert(call); 624 assert(call);
625 LOGGER_DEBUG("Session: %p Handling 'init' friend: %d", call->session, call->friend_number); 625 LOGGER_DEBUG("Session: %p Handling 'init' friend: %d", call->session, call->friend_number);
626 626
627 if (!msg->capabilities.exists) { 627 if (!msg->capabilities.exists) {
628 LOGGER_WARNING("Session: %p Invalid capabilities on 'init'"); 628 LOGGER_WARNING("Session: %p Invalid capabilities on 'init'");
629 call->error = msi_EInvalidMessage; 629 call->error = msi_EInvalidMessage;
630 goto FAILURE; 630 goto FAILURE;
631 } 631 }
632 632
633 switch (call->state) 633 switch (call->state) {
634 {
635 case msi_CallInactive: { 634 case msi_CallInactive: {
636 /* Call requested */ 635 /* Call requested */
637 call->peer_capabilities = msg->capabilities.value; 636 call->peer_capabilities = msg->capabilities.value;
@@ -641,7 +640,7 @@ void handle_init (MSICall* call, const MSIMessage* msg)
641 goto FAILURE; 640 goto FAILURE;
642 } 641 }
643 break; 642 break;
644 643
645 case msi_CallActive: { 644 case msi_CallActive: {
646 /* If peer sent init while the call is already 645 /* If peer sent init while the call is already
647 * active it's probable that he is trying to 646 * active it's probable that he is trying to
@@ -649,9 +648,9 @@ void handle_init (MSICall* call, const MSIMessage* msg)
649 * on our side. We can assume that in this case 648 * on our side. We can assume that in this case
650 * we can automatically answer the re-call. 649 * we can automatically answer the re-call.
651 */ 650 */
652 651
653 LOGGER_INFO("Friend is recalling us"); 652 LOGGER_INFO("Friend is recalling us");
654 653
655 MSIMessage msg; 654 MSIMessage msg;
656 msg_init(&msg, requ_push); 655 msg_init(&msg, requ_push);
657 656
@@ -665,7 +664,7 @@ void handle_init (MSICall* call, const MSIMessage* msg)
665 */ 664 */
666 } 665 }
667 break; 666 break;
668 667
669 default: { 668 default: {
670 LOGGER_WARNING("Session: %p Invalid state on 'init'"); 669 LOGGER_WARNING("Session: %p Invalid state on 'init'");
671 call->error = msi_EInvalidState; 670 call->error = msi_EInvalidState;
@@ -673,7 +672,7 @@ void handle_init (MSICall* call, const MSIMessage* msg)
673 } 672 }
674 break; 673 break;
675 } 674 }
676 675
677 return; 676 return;
678FAILURE: 677FAILURE:
679 send_error(call->session->messenger, call->friend_number, call->error); 678 send_error(call->session->messenger, call->friend_number, call->error);
@@ -746,33 +745,33 @@ void handle_pop (MSICall *call, const MSIMessage *msg)
746 invoke_callback(call, msi_OnError); 745 invoke_callback(call, msi_OnError);
747 746
748 } else switch (call->state) { 747 } else switch (call->state) {
749 case msi_CallInactive: { 748 case msi_CallInactive: {
750 LOGGER_ERROR("Handling what should be impossible case"); 749 LOGGER_ERROR("Handling what should be impossible case");
751 abort(); 750 abort();
752 } 751 }
753 break; 752 break;
754 753
755 case msi_CallActive: { 754 case msi_CallActive: {
756 /* Hangup */ 755 /* Hangup */
757 LOGGER_INFO("Friend hung up on us"); 756 LOGGER_INFO("Friend hung up on us");
758 invoke_callback(call, msi_OnEnd); 757 invoke_callback(call, msi_OnEnd);
759 } 758 }
760 break; 759 break;
761 760
762 case msi_CallRequesting: { 761 case msi_CallRequesting: {
763 /* Reject */ 762 /* Reject */
764 LOGGER_INFO("Friend rejected our call"); 763 LOGGER_INFO("Friend rejected our call");
765 invoke_callback(call, msi_OnEnd); 764 invoke_callback(call, msi_OnEnd);
766 } 765 }
767 break; 766 break;
768 767
769 case msi_CallRequested: { 768 case msi_CallRequested: {
770 /* Cancel */ 769 /* Cancel */
771 LOGGER_INFO("Friend canceled call invite"); 770 LOGGER_INFO("Friend canceled call invite");
772 invoke_callback(call, msi_OnEnd); 771 invoke_callback(call, msi_OnEnd);
772 }
773 break;
773 } 774 }
774 break;
775 }
776 775
777 kill_call (call); 776 kill_call (call);
778} 777}
@@ -814,9 +813,11 @@ void handle_msi_packet (Messenger *m, uint32_t friend_number, const uint8_t *dat
814 case requ_init: 813 case requ_init:
815 handle_init(call, &msg); 814 handle_init(call, &msg);
816 break; 815 break;
816
817 case requ_push: 817 case requ_push:
818 handle_push(call, &msg); 818 handle_push(call, &msg);
819 break; 819 break;
820
820 case requ_pop: 821 case requ_pop:
821 handle_pop(call, &msg); /* always kills the call */ 822 handle_pop(call, &msg); /* always kills the call */
822 break; 823 break;
diff --git a/toxav/rtp.c b/toxav/rtp.c
index 763166cd..1813725a 100644
--- a/toxav/rtp.c
+++ b/toxav/rtp.c
@@ -189,17 +189,18 @@ bool chloss (const RTPSession *session, const struct RTPHeader *header)
189{ 189{
190 if (ntohl(header->timestamp) < session->rtimestamp) { 190 if (ntohl(header->timestamp) < session->rtimestamp) {
191 uint16_t hosq, lost = 0; 191 uint16_t hosq, lost = 0;
192 192
193 hosq = ntohs(header->sequnum); 193 hosq = ntohs(header->sequnum);
194 194
195 lost = (hosq > session->rsequnum) ? 195 lost = (hosq > session->rsequnum) ?
196 (session->rsequnum + 65535) - hosq : 196 (session->rsequnum + 65535) - hosq :
197 session->rsequnum - hosq; 197 session->rsequnum - hosq;
198 198
199 puts ("Lost packet"); 199 puts ("Lost packet");
200
200 while (lost --) 201 while (lost --)
201 bwc_add_lost(session->bwc ,0); 202 bwc_add_lost(session->bwc , 0);
202 203
203 return true; 204 return true;
204 } 205 }
205 206
@@ -251,7 +252,7 @@ int handle_rtp_packet (Messenger *m, uint32_t friendnumber, const uint8_t *data,
251 } 252 }
252 253
253 bwc_feed_avg(session->bwc, length); 254 bwc_feed_avg(session->bwc, length);
254 255
255 if (ntohs(header->tlen) == length - sizeof (struct RTPHeader)) { 256 if (ntohs(header->tlen) == length - sizeof (struct RTPHeader)) {
256 /* The message is sent in single part */ 257 /* The message is sent in single part */
257 258
@@ -267,7 +268,7 @@ int handle_rtp_packet (Messenger *m, uint32_t friendnumber, const uint8_t *data,
267 } 268 }
268 269
269 bwc_add_recv(session->bwc, length); 270 bwc_add_recv(session->bwc, length);
270 271
271 /* Invoke processing of active multiparted message */ 272 /* Invoke processing of active multiparted message */
272 if (session->mp) { 273 if (session->mp) {
273 if (session->mcb) 274 if (session->mcb)
@@ -341,11 +342,11 @@ int handle_rtp_packet (Messenger *m, uint32_t friendnumber, const uint8_t *data,
341 /* Measure missing parts of the old message */ 342 /* Measure missing parts of the old message */
342 bwc_add_lost(session->bwc, 343 bwc_add_lost(session->bwc,
343 (session->mp->header.tlen - session->mp->len) + 344 (session->mp->header.tlen - session->mp->len) +
344 345
345 /* Must account sizes of rtp headers too */ 346 /* Must account sizes of rtp headers too */
346 ((session->mp->header.tlen - session->mp->len) / 347 ((session->mp->header.tlen - session->mp->len) /
347 MAX_CRYPTO_DATA_SIZE) * sizeof(struct RTPHeader) ); 348 MAX_CRYPTO_DATA_SIZE) * sizeof(struct RTPHeader) );
348 349
349 /* Push the previous message for processing */ 350 /* Push the previous message for processing */
350 if (session->mcb) 351 if (session->mcb)
351 session->mcb (session->cs, session->mp); 352 session->mcb (session->cs, session->mp);
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 6a17f55d..9eda3412 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -190,7 +190,7 @@ void toxav_kill(ToxAV *av)
190 return; 190 return;
191 191
192 pthread_mutex_lock(av->mutex); 192 pthread_mutex_lock(av->mutex);
193 193
194 /* To avoid possible deadlocks */ 194 /* To avoid possible deadlocks */
195 while (av->msi && msi_kill(av->msi) != 0) { 195 while (av->msi && msi_kill(av->msi) != 0) {
196 pthread_mutex_unlock(av->mutex); 196 pthread_mutex_unlock(av->mutex);
@@ -206,10 +206,10 @@ void toxav_kill(ToxAV *av)
206 it = call_remove(it); /* This will eventually free av->calls */ 206 it = call_remove(it); /* This will eventually free av->calls */
207 } 207 }
208 } 208 }
209 209
210 pthread_mutex_unlock(av->mutex); 210 pthread_mutex_unlock(av->mutex);
211 pthread_mutex_destroy(av->mutex); 211 pthread_mutex_destroy(av->mutex);
212 212
213 free(av); 213 free(av);
214} 214}
215Tox *toxav_get_tox(const ToxAV *av) 215Tox *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
277 TOXAV_ERR_CALL *error) 277 TOXAV_ERR_CALL *error)
278{ 278{
279 TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK; 279 TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK;
280 280
281 pthread_mutex_lock(av->mutex); 281 pthread_mutex_lock(av->mutex);
282 282
283 if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate)) 283 if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate))
284 || (video_bit_rate && video_bit_rate_invalid(video_bit_rate))) { 284 || (video_bit_rate && video_bit_rate_invalid(video_bit_rate))) {
285 rc = TOXAV_ERR_CALL_INVALID_BIT_RATE; 285 rc = TOXAV_ERR_CALL_INVALID_BIT_RATE;
286 goto END; 286 goto END;
287 } 287 }
@@ -311,7 +311,7 @@ bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint
311 311
312END: 312END:
313 pthread_mutex_unlock(av->mutex); 313 pthread_mutex_unlock(av->mutex);
314 314
315 if (error) 315 if (error)
316 *error = rc; 316 *error = rc;
317 317
@@ -337,7 +337,7 @@ bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, ui
337 } 337 }
338 338
339 if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate)) 339 if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate))
340 || (video_bit_rate && video_bit_rate_invalid(video_bit_rate)) 340 || (video_bit_rate && video_bit_rate_invalid(video_bit_rate))
341 ) { 341 ) {
342 rc = TOXAV_ERR_ANSWER_INVALID_BIT_RATE; 342 rc = TOXAV_ERR_ANSWER_INVALID_BIT_RATE;
343 goto END; 343 goto END;
@@ -441,9 +441,10 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co
441 case TOXAV_CALL_CONTROL_CANCEL: { 441 case TOXAV_CALL_CONTROL_CANCEL: {
442 /* Hang up */ 442 /* Hang up */
443 pthread_mutex_lock(call->mutex); 443 pthread_mutex_lock(call->mutex);
444
444 if (msi_hangup(call->msi_call) != 0) { 445 if (msi_hangup(call->msi_call) != 0) {
445 rc = TOXAV_ERR_CALL_CONTROL_SYNC; 446 rc = TOXAV_ERR_CALL_CONTROL_SYNC;
446 pthread_mutex_unlock(call->mutex); 447 pthread_mutex_unlock(call->mutex);
447 goto END; 448 goto END;
448 } 449 }
449 450
@@ -566,18 +567,22 @@ bool toxav_bit_rate_set(ToxAV *av, uint32_t friend_number, int32_t audio_bit_rat
566 LOGGER_DEBUG("Audio bitrate already set to: %d", audio_bit_rate); 567 LOGGER_DEBUG("Audio bitrate already set to: %d", audio_bit_rate);
567 } else if (audio_bit_rate == 0) { 568 } else if (audio_bit_rate == 0) {
568 LOGGER_DEBUG("Turned off audio sending"); 569 LOGGER_DEBUG("Turned off audio sending");
570
569 if (msi_change_capabilities(call->msi_call, call->msi_call-> 571 if (msi_change_capabilities(call->msi_call, call->msi_call->
570 self_capabilities ^ msi_CapSAudio) != 0) { 572 self_capabilities ^ msi_CapSAudio) != 0) {
571 pthread_mutex_unlock(av->mutex); 573 pthread_mutex_unlock(av->mutex);
572 rc = TOXAV_ERR_BIT_RATE_SET_SYNC; 574 rc = TOXAV_ERR_BIT_RATE_SET_SYNC;
573 goto END; 575 goto END;
574 } 576 }
577
575 /* Audio sending is turned off; notify peer */ 578 /* Audio sending is turned off; notify peer */
576 call->audio_bit_rate = 0; 579 call->audio_bit_rate = 0;
577 } else { 580 } else {
578 pthread_mutex_lock(call->mutex); 581 pthread_mutex_lock(call->mutex);
582
579 if (call->audio_bit_rate == 0) { 583 if (call->audio_bit_rate == 0) {
580 LOGGER_DEBUG("Turned on audio sending"); 584 LOGGER_DEBUG("Turned on audio sending");
585
581 /* The audio has been turned off before this */ 586 /* The audio has been turned off before this */
582 if (msi_change_capabilities(call->msi_call, call-> 587 if (msi_change_capabilities(call->msi_call, call->
583 msi_call->self_capabilities | msi_CapSAudio) != 0) { 588 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
588 } 593 }
589 } else 594 } else
590 LOGGER_DEBUG("Set new audio bit rate %d", audio_bit_rate); 595 LOGGER_DEBUG("Set new audio bit rate %d", audio_bit_rate);
596
591 call->audio_bit_rate = audio_bit_rate; 597 call->audio_bit_rate = audio_bit_rate;
592 pthread_mutex_unlock(call->mutex); 598 pthread_mutex_unlock(call->mutex);
593 } 599 }
@@ -600,6 +606,7 @@ bool toxav_bit_rate_set(ToxAV *av, uint32_t friend_number, int32_t audio_bit_rat
600 LOGGER_DEBUG("Video bitrate already set to: %d", video_bit_rate); 606 LOGGER_DEBUG("Video bitrate already set to: %d", video_bit_rate);
601 } else if (video_bit_rate == 0) { 607 } else if (video_bit_rate == 0) {
602 LOGGER_DEBUG("Turned off video sending"); 608 LOGGER_DEBUG("Turned off video sending");
609
603 /* Video sending is turned off; notify peer */ 610 /* Video sending is turned off; notify peer */
604 if (msi_change_capabilities(call->msi_call, call->msi_call-> 611 if (msi_change_capabilities(call->msi_call, call->msi_call->
605 self_capabilities ^ msi_CapSVideo) != 0) { 612 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
607 rc = TOXAV_ERR_BIT_RATE_SET_SYNC; 614 rc = TOXAV_ERR_BIT_RATE_SET_SYNC;
608 goto END; 615 goto END;
609 } 616 }
617
610 call->video_bit_rate = 0; 618 call->video_bit_rate = 0;
611 } else { 619 } else {
612 pthread_mutex_lock(call->mutex); 620 pthread_mutex_lock(call->mutex);
621
613 if (call->video_bit_rate == 0) { 622 if (call->video_bit_rate == 0) {
614 LOGGER_DEBUG("Turned on video sending"); 623 LOGGER_DEBUG("Turned on video sending");
624
615 /* The video has been turned off before this */ 625 /* The video has been turned off before this */
616 if (msi_change_capabilities(call->msi_call, call-> 626 if (msi_change_capabilities(call->msi_call, call->
617 msi_call->self_capabilities | msi_CapSVideo) != 0) { 627 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
622 } 632 }
623 } else 633 } else
624 LOGGER_DEBUG("Set new video bit rate %d", video_bit_rate); 634 LOGGER_DEBUG("Set new video bit rate %d", video_bit_rate);
635
625 call->video_bit_rate = video_bit_rate; 636 call->video_bit_rate = video_bit_rate;
626 pthread_mutex_unlock(call->mutex); 637 pthread_mutex_unlock(call->mutex);
627 } 638 }
628 } 639 }
629 640
630 pthread_mutex_unlock(av->mutex); 641 pthread_mutex_unlock(av->mutex);
631END: 642END:
643
632 if (error) 644 if (error)
633 *error = rc; 645 *error = rc;
634 646
@@ -656,7 +668,7 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc
656 rc = TOXAV_ERR_SEND_FRAME_SYNC; 668 rc = TOXAV_ERR_SEND_FRAME_SYNC;
657 goto END; 669 goto END;
658 } 670 }
659 671
660 call = call_get(av, friend_number); 672 call = call_get(av, friend_number);
661 673
662 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { 674 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
719 pthread_mutex_unlock(call->mutex_audio); 731 pthread_mutex_unlock(call->mutex_audio);
720 732
721END: 733END:
734
722 if (error) 735 if (error)
723 *error = rc; 736 *error = rc;
724 737
@@ -739,7 +752,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u
739 rc = TOXAV_ERR_SEND_FRAME_SYNC; 752 rc = TOXAV_ERR_SEND_FRAME_SYNC;
740 goto END; 753 goto END;
741 } 754 }
742 755
743 call = call_get(av, friend_number); 756 call = call_get(av, friend_number);
744 757
745 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { 758 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
817 pthread_mutex_unlock(call->mutex_video); 830 pthread_mutex_unlock(call->mutex_video);
818 831
819END: 832END:
833
820 if (error) 834 if (error)
821 *error = rc; 835 *error = rc;
822 836
@@ -843,7 +857,7 @@ void toxav_callback_video_receive_frame(ToxAV *av, toxav_video_receive_frame_cb
843 * :: Internal 857 * :: Internal
844 * 858 *
845 ******************************************************************************/ 859 ******************************************************************************/
846void callback_bwc(BWControler* bwc, uint32_t friend_number, float loss, void* user_data) 860void callback_bwc(BWControler *bwc, uint32_t friend_number, float loss, void *user_data)
847{ 861{
848 /* Callback which is called when the internal measure mechanism reported packet loss. 862 /* Callback which is called when the internal measure mechanism reported packet loss.
849 * We report suggested lowered bitrate to an app. If app is sending both audio and video, 863 * 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
851 * takes more than 90% bandwidth. Otherwise, we report lowered bitrate on audio. 865 * takes more than 90% bandwidth. Otherwise, we report lowered bitrate on audio.
852 * The application may choose to disable video totally if the stream is too bad. 866 * The application may choose to disable video totally if the stream is too bad.
853 */ 867 */
854 868
855 ToxAVCall* call = user_data; 869 ToxAVCall *call = user_data;
856 assert(call); 870 assert(call);
857 871
858 LOGGER_DEBUG("Reported loss of %f%%", loss*100); 872 LOGGER_DEBUG("Reported loss of %f%%", loss * 100);
859 873
860 if (loss < .01f) 874 if (loss < .01f)
861 return; 875 return;
862 876
863 pthread_mutex_lock(call->av->mutex); 877 pthread_mutex_lock(call->av->mutex);
878
864 if (!call->av->bcb.first) { 879 if (!call->av->bcb.first) {
865 pthread_mutex_unlock(call->av->mutex); 880 pthread_mutex_unlock(call->av->mutex);
866 LOGGER_WARNING("No callback to report loss on"); 881 LOGGER_WARNING("No callback to report loss on");
867 return; 882 return;
868 } 883 }
869 884
870 if (call->video_bit_rate) 885 if (call->video_bit_rate)
871 (*call->av->bcb.first) (call->av, friend_number, call->audio_bit_rate, 886 (*call->av->bcb.first) (call->av, friend_number, call->audio_bit_rate,
872 call->video_bit_rate - (call->video_bit_rate * loss), 887 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
875 (*call->av->bcb.first) (call->av, friend_number, 890 (*call->av->bcb.first) (call->av, friend_number,
876 call->audio_bit_rate - (call->audio_bit_rate * loss), 891 call->audio_bit_rate - (call->audio_bit_rate * loss),
877 0, call->av->bcb.second); 892 0, call->av->bcb.second);
878 893
879 pthread_mutex_unlock(call->av->mutex); 894 pthread_mutex_unlock(call->av->mutex);
880} 895}
881int callback_invite(void *toxav_inst, MSICall *call) 896int callback_invite(void *toxav_inst, MSICall *call)
@@ -1167,7 +1182,7 @@ bool call_prepare_transmission(ToxAVCall *call)
1167 1182
1168 /* Prepare bwc */ 1183 /* Prepare bwc */
1169 call->bwc = bwc_new(av->m, call->friend_number, callback_bwc, call); 1184 call->bwc = bwc_new(av->m, call->friend_number, callback_bwc, call);
1170 1185
1171 { /* Prepare audio */ 1186 { /* Prepare audio */
1172 call->audio.second = ac_new(av, call->friend_number, av->acb.first, av->acb.second); 1187 call->audio.second = ac_new(av, call->friend_number, av->acb.first, av->acb.second);
1173 1188
@@ -1236,7 +1251,7 @@ void call_kill_transmission(ToxAVCall *call)
1236 pthread_mutex_unlock(call->mutex); 1251 pthread_mutex_unlock(call->mutex);
1237 1252
1238 bwc_kill(call->bwc); 1253 bwc_kill(call->bwc);
1239 1254
1240 rtp_kill(call->audio.first); 1255 rtp_kill(call->audio.first);
1241 ac_kill(call->audio.second); 1256 ac_kill(call->audio.second);
1242 call->audio.first = NULL; 1257 call->audio.first = NULL;
diff --git a/toxav/toxav.h b/toxav/toxav.h
index 5c5195b3..08a6d265 100644
--- a/toxav/toxav.h
+++ b/toxav/toxav.h
@@ -1,5 +1,5 @@
1/* toxav.h 1/* toxav.h
2 * 2 *
3 * Copyright (C) 2013-2015 Tox project All Rights Reserved. 3 * Copyright (C) 2013-2015 Tox project All Rights Reserved.
4 * 4 *
5 * This file is part of Tox. 5 * This file is part of Tox.
@@ -16,7 +16,7 @@
16 * 16 *
17 * You should have received a copy of the GNU General Public License 17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>. 18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 * 19 *
20 */ 20 */
21 21
22#ifndef TOXAV_H 22#ifndef TOXAV_H
@@ -31,37 +31,37 @@ extern "C" {
31#endif 31#endif
32 32
33/** \page av Public audio/video API for Tox clients. 33/** \page av Public audio/video API for Tox clients.
34 * 34 *
35 * This API can handle multiple calls. Each call has its state, in very rare 35 * This API can handle multiple calls. Each call has its state, in very rare
36 * occasions the library can change the state of the call without apps knowledge. 36 * occasions the library can change the state of the call without apps knowledge.
37 * 37 *
38 */ 38 */
39/** \subsection events Events and callbacks 39/** \subsection events Events and callbacks
40 * 40 *
41 * As in Core API, events are handled by callbacks. One callback can be 41 * As in Core API, events are handled by callbacks. One callback can be
42 * registered per event. All events have a callback function type named 42 * registered per event. All events have a callback function type named
43 * `toxav_{event}_cb` and a function to register it named `toxav_callback_{event}`. 43 * `toxav_{event}_cb` and a function to register it named `toxav_callback_{event}`.
44 * Passing a NULL callback will result in no callback being registered for that 44 * Passing a NULL callback will result in no callback being registered for that
45 * event. Only one callback per event can be registered, so if a client needs 45 * event. Only one callback per event can be registered, so if a client needs
46 * multiple event listeners, it needs to implement the dispatch functionality 46 * multiple event listeners, it needs to implement the dispatch functionality
47 * itself. Unlike Core API, lack of some event handlers will cause the the 47 * itself. Unlike Core API, lack of some event handlers will cause the the
48 * library to drop calls before they are started. Hanging up call from a 48 * library to drop calls before they are started. Hanging up call from a
49 * callback causes undefined behaviour. 49 * callback causes undefined behaviour.
50 * 50 *
51 */ 51 */
52/** \subsection threading Threading implications 52/** \subsection threading Threading implications
53 * 53 *
54 * Unlike the Core API, this API is fully thread-safe. The library will ensure 54 * Unlike the Core API, this API is fully thread-safe. The library will ensure
55 * the proper synchronization of parallel calls. 55 * the proper synchronization of parallel calls.
56 * 56 *
57 * A common way to run ToxAV (multiple or single instance) is to have a thread, 57 * A common way to run ToxAV (multiple or single instance) is to have a thread,
58 * separate from tox instance thread, running a simple toxav_iterate loop, 58 * separate from tox instance thread, running a simple toxav_iterate loop,
59 * sleeping for toxav_iteration_interval * milliseconds on each iteration. 59 * sleeping for toxav_iteration_interval * milliseconds on each iteration.
60 * 60 *
61 * An important thing to note is that events are triggered from both tox and 61 * An important thing to note is that events are triggered from both tox and
62 * toxav thread (see above). Audio and video receive frame events are triggered 62 * toxav thread (see above). Audio and video receive frame events are triggered
63 * from toxav thread while all the other events are triggered from tox thread. 63 * from toxav thread while all the other events are triggered from tox thread.
64 * 64 *
65 * Tox thread has priority with mutex mechanisms. Any api function can 65 * Tox thread has priority with mutex mechanisms. Any api function can
66 * fail if mutexes are held by tox thread in which case they will set SYNC 66 * fail if mutexes are held by tox thread in which case they will set SYNC
67 * error code. 67 * error code.
@@ -81,9 +81,9 @@ typedef struct Tox Tox;
81 * The ToxAV instance type. Each ToxAV instance can be bound to only one Tox 81 * The ToxAV instance type. Each ToxAV instance can be bound to only one Tox
82 * instance, and Tox instance can have only one ToxAV instance. One must make 82 * instance, and Tox instance can have only one ToxAV instance. One must make
83 * sure to close ToxAV instance prior closing Tox instance otherwise undefined 83 * sure to close ToxAV instance prior closing Tox instance otherwise undefined
84 * behaviour occurs. Upon closing of ToxAV instance, all active calls will be 84 * behaviour occurs. Upon closing of ToxAV instance, all active calls will be
85 * forcibly terminated without notifying peers. 85 * forcibly terminated without notifying peers.
86 * 86 *
87 */ 87 */
88#ifndef TOXAV_DEFINED 88#ifndef TOXAV_DEFINED
89#define TOXAV_DEFINED 89#define TOXAV_DEFINED
@@ -164,28 +164,28 @@ bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
164 164
165 165
166/******************************************************************************* 166/*******************************************************************************
167 * 167 *
168 * :: Creation and destruction 168 * :: Creation and destruction
169 * 169 *
170 ******************************************************************************/ 170 ******************************************************************************/
171typedef enum TOXAV_ERR_NEW { 171typedef enum TOXAV_ERR_NEW {
172 /** 172 /**
173 * The function returned successfully. 173 * The function returned successfully.
174 */ 174 */
175 TOXAV_ERR_NEW_OK, 175 TOXAV_ERR_NEW_OK,
176 /** 176 /**
177 * One of the arguments to the function was NULL when it was not expected. 177 * One of the arguments to the function was NULL when it was not expected.
178 */ 178 */
179 TOXAV_ERR_NEW_NULL, 179 TOXAV_ERR_NEW_NULL,
180 /** 180 /**
181 * Memory allocation failure while trying to allocate structures required for 181 * Memory allocation failure while trying to allocate structures required for
182 * the A/V session. 182 * the A/V session.
183 */ 183 */
184 TOXAV_ERR_NEW_MALLOC, 184 TOXAV_ERR_NEW_MALLOC,
185 /** 185 /**
186 * Attempted to create a second session for the same Tox instance. 186 * Attempted to create a second session for the same Tox instance.
187 */ 187 */
188 TOXAV_ERR_NEW_MULTIPLE, 188 TOXAV_ERR_NEW_MULTIPLE,
189} TOXAV_ERR_NEW; 189} TOXAV_ERR_NEW;
190 190
191/** 191/**
@@ -209,7 +209,7 @@ Tox *toxav_get_tox(const ToxAV *toxAV);
209 209
210 210
211/******************************************************************************* 211/*******************************************************************************
212 * 212 *
213 * :: A/V event loop 213 * :: A/V event loop
214 * 214 *
215 ******************************************************************************/ 215 ******************************************************************************/
@@ -221,48 +221,48 @@ uint32_t toxav_iteration_interval(const ToxAV *toxAV);
221 221
222/** 222/**
223 * Main loop for the session. This function needs to be called in intervals of 223 * Main loop for the session. This function needs to be called in intervals of
224 * toxav_iteration_interval() milliseconds. It is best called in the separate 224 * toxav_iteration_interval() milliseconds. It is best called in the separate
225 * thread from tox_iterate. 225 * thread from tox_iterate.
226 */ 226 */
227void toxav_iterate(ToxAV *toxAV); 227void toxav_iterate(ToxAV *toxAV);
228 228
229 229
230/******************************************************************************* 230/*******************************************************************************
231 * 231 *
232 * :: Call setup 232 * :: Call setup
233 * 233 *
234 ******************************************************************************/ 234 ******************************************************************************/
235typedef enum TOXAV_ERR_CALL { 235typedef enum TOXAV_ERR_CALL {
236 /** 236 /**
237 * The function returned successfully. 237 * The function returned successfully.
238 */ 238 */
239 TOXAV_ERR_CALL_OK, 239 TOXAV_ERR_CALL_OK,
240 /** 240 /**
241 * A resource allocation error occurred while trying to create the structures 241 * A resource allocation error occurred while trying to create the structures
242 * required for the call. 242 * required for the call.
243 */ 243 */
244 TOXAV_ERR_CALL_MALLOC, 244 TOXAV_ERR_CALL_MALLOC,
245 /** 245 /**
246 * Synchronization error occurred. 246 * Synchronization error occurred.
247 */ 247 */
248 TOXAV_ERR_CALL_SYNC, 248 TOXAV_ERR_CALL_SYNC,
249 /** 249 /**
250 * The friend number did not designate a valid friend. 250 * The friend number did not designate a valid friend.
251 */ 251 */
252 TOXAV_ERR_CALL_FRIEND_NOT_FOUND, 252 TOXAV_ERR_CALL_FRIEND_NOT_FOUND,
253 /** 253 /**
254 * The friend was valid, but not currently connected. 254 * The friend was valid, but not currently connected.
255 */ 255 */
256 TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED, 256 TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED,
257 /** 257 /**
258 * Attempted to call a friend while already in an audio or video call with 258 * Attempted to call a friend while already in an audio or video call with
259 * them. 259 * them.
260 */ 260 */
261 TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL, 261 TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL,
262 /** 262 /**
263 * Audio or video bit rate is invalid. 263 * Audio or video bit rate is invalid.
264 */ 264 */
265 TOXAV_ERR_CALL_INVALID_BIT_RATE, 265 TOXAV_ERR_CALL_INVALID_BIT_RATE,
266} TOXAV_ERR_CALL; 266} TOXAV_ERR_CALL;
267 267
268/** 268/**
@@ -270,7 +270,7 @@ typedef enum TOXAV_ERR_CALL {
270 * 270 *
271 * It is the client's responsibility to stop ringing after a certain timeout, 271 * It is the client's responsibility to stop ringing after a certain timeout,
272 * if such behaviour is desired. If the client does not stop ringing, the 272 * if such behaviour is desired. If the client does not stop ringing, the
273 * library will not stop until the friend is disconnected. Audio and video 273 * library will not stop until the friend is disconnected. Audio and video
274 * receiving are both enabled by default. 274 * receiving are both enabled by default.
275 * 275 *
276 * @param friend_number The friend number of the friend that should be called. 276 * @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,
284 284
285/** 285/**
286 * The function type for the call callback. 286 * The function type for the call callback.
287 * 287 *
288 * @param friend_number The friend number from which the call is incoming. 288 * @param friend_number The friend number from which the call is incoming.
289 * @param audio_enabled True if friend is sending audio. 289 * @param audio_enabled True if friend is sending audio.
290 * @param video_enabled True if friend is sending video. 290 * @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
299void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data); 299void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data);
300 300
301typedef enum TOXAV_ERR_ANSWER { 301typedef enum TOXAV_ERR_ANSWER {
302 /** 302 /**
303 * The function returned successfully. 303 * The function returned successfully.
304 */ 304 */
305 TOXAV_ERR_ANSWER_OK, 305 TOXAV_ERR_ANSWER_OK,
306 /** 306 /**
307 * Synchronization error occurred. 307 * Synchronization error occurred.
308 */ 308 */
309 TOXAV_ERR_ANSWER_SYNC, 309 TOXAV_ERR_ANSWER_SYNC,
310 /** 310 /**
311 * Failed to initialize codecs for call session. Note that codec initiation 311 * Failed to initialize codecs for call session. Note that codec initiation
312 * will fail if there is no receive callback registered for either audio or 312 * will fail if there is no receive callback registered for either audio or
313 * video. 313 * video.
314 */ 314 */
315 TOXAV_ERR_ANSWER_CODEC_INITIALIZATION, 315 TOXAV_ERR_ANSWER_CODEC_INITIALIZATION,
316 /** 316 /**
317 * The friend number did not designate a valid friend. 317 * The friend number did not designate a valid friend.
318 */ 318 */
319 TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND, 319 TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND,
320 /** 320 /**
321 * The friend was valid, but they are not currently trying to initiate a call. 321 * The friend was valid, but they are not currently trying to initiate a call.
322 * This is also returned if this client is already in a call with the friend. 322 * This is also returned if this client is already in a call with the friend.
323 */ 323 */
324 TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING, 324 TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING,
325 /** 325 /**
326 * Audio or video bit rate is invalid. 326 * Audio or video bit rate is invalid.
327 */ 327 */
328 TOXAV_ERR_ANSWER_INVALID_BIT_RATE, 328 TOXAV_ERR_ANSWER_INVALID_BIT_RATE,
329} TOXAV_ERR_ANSWER; 329} TOXAV_ERR_ANSWER;
330 330
331/** 331/**
@@ -341,44 +341,45 @@ typedef enum TOXAV_ERR_ANSWER {
341 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable 341 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable
342 * video sending. 342 * video sending.
343 */ 343 */
344bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error); 344bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate,
345 TOXAV_ERR_ANSWER *error);
345 346
346 347
347/******************************************************************************* 348/*******************************************************************************
348 * 349 *
349 * :: Call state graph 350 * :: Call state graph
350 * 351 *
351 ******************************************************************************/ 352 ******************************************************************************/
352enum TOXAV_FRIEND_CALL_STATE { 353enum TOXAV_FRIEND_CALL_STATE {
353 /** 354 /**
354 * Set by the AV core if an error occurred on the remote end or if friend 355 * Set by the AV core if an error occurred on the remote end or if friend
355 * timed out. This is the final state after which no more state 356 * timed out. This is the final state after which no more state
356 * transitions can occur for the call. This call state will never be triggered 357 * transitions can occur for the call. This call state will never be triggered
357 * in combination with other call states. 358 * in combination with other call states.
358 */ 359 */
359 TOXAV_FRIEND_CALL_STATE_ERROR = 1, 360 TOXAV_FRIEND_CALL_STATE_ERROR = 1,
360 /** 361 /**
361 * The call has finished. This is the final state after which no more state 362 * The call has finished. This is the final state after which no more state
362 * transitions can occur for the call. This call state will never be 363 * transitions can occur for the call. This call state will never be
363 * triggered in combination with other call states. 364 * triggered in combination with other call states.
364 */ 365 */
365 TOXAV_FRIEND_CALL_STATE_FINISHED = 2, 366 TOXAV_FRIEND_CALL_STATE_FINISHED = 2,
366 /** 367 /**
367 * The flag that marks that friend is sending audio. 368 * The flag that marks that friend is sending audio.
368 */ 369 */
369 TOXAV_FRIEND_CALL_STATE_SENDING_A = 4, 370 TOXAV_FRIEND_CALL_STATE_SENDING_A = 4,
370 /** 371 /**
371 * The flag that marks that friend is sending video. 372 * The flag that marks that friend is sending video.
372 */ 373 */
373 TOXAV_FRIEND_CALL_STATE_SENDING_V = 8, 374 TOXAV_FRIEND_CALL_STATE_SENDING_V = 8,
374 /** 375 /**
375 * The flag that marks that friend is receiving audio. 376 * The flag that marks that friend is receiving audio.
376 */ 377 */
377 TOXAV_FRIEND_CALL_STATE_ACCEPTING_A = 16, 378 TOXAV_FRIEND_CALL_STATE_ACCEPTING_A = 16,
378 /** 379 /**
379 * The flag that marks that friend is receiving video. 380 * The flag that marks that friend is receiving video.
380 */ 381 */
381 TOXAV_FRIEND_CALL_STATE_ACCEPTING_V = 32, 382 TOXAV_FRIEND_CALL_STATE_ACCEPTING_V = 32,
382}; 383};
383 384
384/** 385/**
@@ -399,70 +400,70 @@ typedef void toxav_call_state_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t
399void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data); 400void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data);
400 401
401/******************************************************************************* 402/*******************************************************************************
402 * 403 *
403 * :: Call control 404 * :: Call control
404 * 405 *
405 ******************************************************************************/ 406 ******************************************************************************/
406typedef enum TOXAV_CALL_CONTROL { 407typedef enum TOXAV_CALL_CONTROL {
407 /** 408 /**
408 * Resume a previously paused call. Only valid if the pause was caused by this 409 * Resume a previously paused call. Only valid if the pause was caused by this
409 * client, if not, this control is ignored. Not valid before the call is accepted. 410 * client, if not, this control is ignored. Not valid before the call is accepted.
410 */ 411 */
411 TOXAV_CALL_CONTROL_RESUME, 412 TOXAV_CALL_CONTROL_RESUME,
412 /** 413 /**
413 * Put a call on hold. Not valid before the call is accepted. 414 * Put a call on hold. Not valid before the call is accepted.
414 */ 415 */
415 TOXAV_CALL_CONTROL_PAUSE, 416 TOXAV_CALL_CONTROL_PAUSE,
416 /** 417 /**
417 * Reject a call if it was not answered, yet. Cancel a call after it was 418 * Reject a call if it was not answered, yet. Cancel a call after it was
418 * answered. 419 * answered.
419 */ 420 */
420 TOXAV_CALL_CONTROL_CANCEL, 421 TOXAV_CALL_CONTROL_CANCEL,
421 /** 422 /**
422 * Request that the friend stops sending audio. Regardless of the friend's 423 * Request that the friend stops sending audio. Regardless of the friend's
423 * compliance, this will cause the audio_receive_frame event to stop being 424 * compliance, this will cause the audio_receive_frame event to stop being
424 * triggered on receiving an audio frame from the friend. 425 * triggered on receiving an audio frame from the friend.
425 */ 426 */
426 TOXAV_CALL_CONTROL_MUTE_AUDIO, 427 TOXAV_CALL_CONTROL_MUTE_AUDIO,
427 /** 428 /**
428 * Calling this control will notify client to start sending audio again. 429 * Calling this control will notify client to start sending audio again.
429 */ 430 */
430 TOXAV_CALL_CONTROL_UNMUTE_AUDIO, 431 TOXAV_CALL_CONTROL_UNMUTE_AUDIO,
431 /** 432 /**
432 * Request that the friend stops sending video. Regardless of the friend's 433 * Request that the friend stops sending video. Regardless of the friend's
433 * compliance, this will cause the video_receive_frame event to stop being 434 * compliance, this will cause the video_receive_frame event to stop being
434 * triggered on receiving a video frame from the friend. 435 * triggered on receiving a video frame from the friend.
435 */ 436 */
436 TOXAV_CALL_CONTROL_HIDE_VIDEO, 437 TOXAV_CALL_CONTROL_HIDE_VIDEO,
437 /** 438 /**
438 * Calling this control will notify client to start sending video again. 439 * Calling this control will notify client to start sending video again.
439 */ 440 */
440 TOXAV_CALL_CONTROL_SHOW_VIDEO, 441 TOXAV_CALL_CONTROL_SHOW_VIDEO,
441} TOXAV_CALL_CONTROL; 442} TOXAV_CALL_CONTROL;
442 443
443typedef enum TOXAV_ERR_CALL_CONTROL { 444typedef enum TOXAV_ERR_CALL_CONTROL {
444 /** 445 /**
445 * The function returned successfully. 446 * The function returned successfully.
446 */ 447 */
447 TOXAV_ERR_CALL_CONTROL_OK, 448 TOXAV_ERR_CALL_CONTROL_OK,
448 /** 449 /**
449 * Synchronization error occurred. 450 * Synchronization error occurred.
450 */ 451 */
451 TOXAV_ERR_CALL_CONTROL_SYNC, 452 TOXAV_ERR_CALL_CONTROL_SYNC,
452 /** 453 /**
453 * The friend_number passed did not designate a valid friend. 454 * The friend_number passed did not designate a valid friend.
454 */ 455 */
455 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND, 456 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND,
456 /** 457 /**
457 * This client is currently not in a call with the friend. Before the call is 458 * This client is currently not in a call with the friend. Before the call is
458 * answered, only CANCEL is a valid control. 459 * answered, only CANCEL is a valid control.
459 */ 460 */
460 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL, 461 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL,
461 /** 462 /**
462 * Happens if user tried to pause an already paused call or if trying to 463 * Happens if user tried to pause an already paused call or if trying to
463 * resume a call that is not paused. 464 * resume a call that is not paused.
464 */ 465 */
465 TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION, 466 TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION,
466} TOXAV_ERR_CALL_CONTROL; 467} TOXAV_ERR_CALL_CONTROL;
467 468
468/** 469/**
@@ -474,39 +475,40 @@ typedef enum TOXAV_ERR_CALL_CONTROL {
474 * 475 *
475 * @return true on success. 476 * @return true on success.
476 */ 477 */
477bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error); 478bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control,
479 TOXAV_ERR_CALL_CONTROL *error);
478 480
479 481
480/******************************************************************************* 482/*******************************************************************************
481 * 483 *
482 * :: Controlling bit rates 484 * :: Controlling bit rates
483 * 485 *
484 ******************************************************************************/ 486 ******************************************************************************/
485typedef enum TOXAV_ERR_BIT_RATE_SET { 487typedef enum TOXAV_ERR_BIT_RATE_SET {
486 /** 488 /**
487 * The function returned successfully. 489 * The function returned successfully.
488 */ 490 */
489 TOXAV_ERR_BIT_RATE_SET_OK, 491 TOXAV_ERR_BIT_RATE_SET_OK,
490 /** 492 /**
491 * Synchronization error occurred. 493 * Synchronization error occurred.
492 */ 494 */
493 TOXAV_ERR_BIT_RATE_SET_SYNC, 495 TOXAV_ERR_BIT_RATE_SET_SYNC,
494 /** 496 /**
495 * The audio bit rate passed was not one of the supported values. 497 * The audio bit rate passed was not one of the supported values.
496 */ 498 */
497 TOXAV_ERR_BIT_RATE_SET_INVALID_AUDIO_BIT_RATE, 499 TOXAV_ERR_BIT_RATE_SET_INVALID_AUDIO_BIT_RATE,
498 /** 500 /**
499 * The video bit rate passed was not one of the supported values. 501 * The video bit rate passed was not one of the supported values.
500 */ 502 */
501 TOXAV_ERR_BIT_RATE_SET_INVALID_VIDEO_BIT_RATE, 503 TOXAV_ERR_BIT_RATE_SET_INVALID_VIDEO_BIT_RATE,
502 /** 504 /**
503 * The friend_number passed did not designate a valid friend. 505 * The friend_number passed did not designate a valid friend.
504 */ 506 */
505 TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND, 507 TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND,
506 /** 508 /**
507 * This client is currently not in a call with the friend. 509 * This client is currently not in a call with the friend.
508 */ 510 */
509 TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL, 511 TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL,
510} TOXAV_ERR_BIT_RATE_SET; 512} TOXAV_ERR_BIT_RATE_SET;
511 513
512/** 514/**
@@ -518,22 +520,23 @@ typedef enum TOXAV_ERR_BIT_RATE_SET {
518 * audio sending. Set to -1 to leave unchanged. 520 * audio sending. Set to -1 to leave unchanged.
519 * @param video_bit_rate The new video bit rate in Kb/sec. Set to 0 to disable 521 * @param video_bit_rate The new video bit rate in Kb/sec. Set to 0 to disable
520 * video sending. Set to -1 to leave unchanged. 522 * video sending. Set to -1 to leave unchanged.
521 * 523 *
522 */ 524 */
523bool toxav_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, int32_t audio_bit_rate, 525bool toxav_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, int32_t audio_bit_rate,
524 int32_t video_bit_rate, TOXAV_ERR_BIT_RATE_SET *error); 526 int32_t video_bit_rate, TOXAV_ERR_BIT_RATE_SET *error);
525 527
526/** 528/**
527 * The function type for the bit_rate_status callback. The event is triggered 529 * The function type for the bit_rate_status callback. The event is triggered
528 * when the network becomes too saturated for current bit rates at which 530 * when the network becomes too saturated for current bit rates at which
529 * point core suggests new bit rates. 531 * point core suggests new bit rates.
530 * 532 *
531 * @param friend_number The friend number of the friend for which to set the 533 * @param friend_number The friend number of the friend for which to set the
532 * bit rate. 534 * bit rate.
533 * @param audio_bit_rate Suggested maximum audio bit rate in Kb/sec. 535 * @param audio_bit_rate Suggested maximum audio bit rate in Kb/sec.
534 * @param video_bit_rate Suggested maximum video bit rate in Kb/sec. 536 * @param video_bit_rate Suggested maximum video bit rate in Kb/sec.
535 */ 537 */
536typedef 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); 538typedef void toxav_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate,
539 uint32_t video_bit_rate, void *user_data);
537 540
538/** 541/**
539 * Set the callback for the `bit_rate_status` event. Pass NULL to unset. 542 * 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
543 546
544 547
545/******************************************************************************* 548/*******************************************************************************
546 * 549 *
547 * :: A/V sending 550 * :: A/V sending
548 * 551 *
549 ******************************************************************************/ 552 ******************************************************************************/
550typedef enum TOXAV_ERR_SEND_FRAME { 553typedef enum TOXAV_ERR_SEND_FRAME {
551 /** 554 /**
552 * The function returned successfully. 555 * The function returned successfully.
553 */ 556 */
554 TOXAV_ERR_SEND_FRAME_OK, 557 TOXAV_ERR_SEND_FRAME_OK,
555 /** 558 /**
556 * In case of video, one of Y, U, or V was NULL. In case of audio, the samples 559 * In case of video, one of Y, U, or V was NULL. In case of audio, the samples
557 * data pointer was NULL. 560 * data pointer was NULL.
558 */ 561 */
559 TOXAV_ERR_SEND_FRAME_NULL, 562 TOXAV_ERR_SEND_FRAME_NULL,
560 /** 563 /**
561 * The friend_number passed did not designate a valid friend. 564 * The friend_number passed did not designate a valid friend.
562 */ 565 */
563 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND, 566 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND,
564 /** 567 /**
565 * This client is currently not in a call with the friend. 568 * This client is currently not in a call with the friend.
566 */ 569 */
567 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL, 570 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL,
568 /** 571 /**
569 * Synchronization error occurred. 572 * Synchronization error occurred.
570 */ 573 */
571 TOXAV_ERR_SEND_FRAME_SYNC, 574 TOXAV_ERR_SEND_FRAME_SYNC,
572 /** 575 /**
573 * One of the frame parameters was invalid. E.g. the resolution may be too 576 * One of the frame parameters was invalid. E.g. the resolution may be too
574 * small or too large, or the audio sampling rate may be unsupported. 577 * small or too large, or the audio sampling rate may be unsupported.
575 */ 578 */
576 TOXAV_ERR_SEND_FRAME_INVALID, 579 TOXAV_ERR_SEND_FRAME_INVALID,
577 /** 580 /**
578 * Either friend turned off audio or video receiving or we turned off sending 581 * Either friend turned off audio or video receiving or we turned off sending
579 * for the said payload. 582 * for the said payload.
580 */ 583 */
581 TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED, 584 TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED,
582 /** 585 /**
583 * Failed to push frame through rtp interface. 586 * Failed to push frame through rtp interface.
584 */ 587 */
585 TOXAV_ERR_SEND_FRAME_RTP_FAILED, 588 TOXAV_ERR_SEND_FRAME_RTP_FAILED,
586} TOXAV_ERR_SEND_FRAME; 589} TOXAV_ERR_SEND_FRAME;
587 590
588/** 591/**
@@ -605,7 +608,7 @@ typedef enum TOXAV_ERR_SEND_FRAME {
605 * @param sampling_rate Audio sampling rate used in this frame. Valid sampling 608 * @param sampling_rate Audio sampling rate used in this frame. Valid sampling
606 * rates are 8000, 12000, 16000, 24000, or 48000. 609 * rates are 8000, 12000, 16000, 24000, or 48000.
607 */ 610 */
608bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, 611bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm,
609 size_t sample_count, uint8_t channels, uint32_t sampling_rate, 612 size_t sample_count, uint8_t channels, uint32_t sampling_rate,
610 TOXAV_ERR_SEND_FRAME *error); 613 TOXAV_ERR_SEND_FRAME *error);
611 614
@@ -624,13 +627,13 @@ bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t
624 * @param u U (Chroma) plane data. 627 * @param u U (Chroma) plane data.
625 * @param v V (Chroma) plane data. 628 * @param v V (Chroma) plane data.
626 */ 629 */
627bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width, 630bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width,
628 uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, 631 uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v,
629 TOXAV_ERR_SEND_FRAME *error); 632 TOXAV_ERR_SEND_FRAME *error);
630 633
631 634
632/******************************************************************************* 635/*******************************************************************************
633 * 636 *
634 * :: A/V receiving 637 * :: A/V receiving
635 * 638 *
636 ******************************************************************************/ 639 ******************************************************************************/
@@ -638,7 +641,7 @@ bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width
638 * The function type for the audio_receive_frame callback. The callback can be 641 * The function type for the audio_receive_frame callback. The callback can be
639 * called multiple times per single iteration depending on the amount of queued 642 * called multiple times per single iteration depending on the amount of queued
640 * frames in the buffer. The received format is the same as in send function. 643 * frames in the buffer. The received format is the same as in send function.
641 * 644 *
642 * @param friend_number The friend number of the friend who sent an audio frame. 645 * @param friend_number The friend number of the friend who sent an audio frame.
643 * @param pcm An array of audio samples (sample_count * channels elements). 646 * @param pcm An array of audio samples (sample_count * channels elements).
644 * @param sample_count The number of audio samples per channel in the PCM array. 647 * @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
647 * 650 *
648 */ 651 */
649typedef void toxav_audio_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, 652typedef void toxav_audio_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm,
650 size_t sample_count, uint8_t channels, uint32_t sampling_rate, 653 size_t sample_count, uint8_t channels, uint32_t sampling_rate,
651 void *user_data); 654 void *user_data);
652 655
653/** 656/**
654 * Set the callback for the `audio_receive_frame` event. Pass NULL to unset. 657 * 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_
662 * @param friend_number The friend number of the friend who sent a video frame. 665 * @param friend_number The friend number of the friend who sent a video frame.
663 * @param width Width of the frame in pixels. 666 * @param width Width of the frame in pixels.
664 * @param height Height of the frame in pixels. 667 * @param height Height of the frame in pixels.
665 * @param y 668 * @param y
666 * @param u 669 * @param u
667 * @param v Plane data. 670 * @param v Plane data.
668 * The size of plane data is derived from width and height where 671 * The size of plane data is derived from width and height where
669 * Y = MAX(width, abs(ystride)) * height, 672 * Y = MAX(width, abs(ystride)) * height,
670 * U = MAX(width/2, abs(ustride)) * (height/2) and 673 * U = MAX(width/2, abs(ustride)) * (height/2) and
671 * V = MAX(width/2, abs(vstride)) * (height/2). 674 * V = MAX(width/2, abs(vstride)) * (height/2).
672 * @param ystride 675 * @param ystride
673 * @param ustride 676 * @param ustride
674 * @param vstride Strides data. Strides represent padding for each plane 677 * @param vstride Strides data. Strides represent padding for each plane
675 * that may or may not be present. You must handle strides in 678 * that may or may not be present. You must handle strides in
676 * your image processing code. Strides are negative if the 679 * your image processing code. Strides are negative if the
677 * image is bottom-up hence why you MUST abs() it when 680 * image is bottom-up hence why you MUST abs() it when
678 * calculating plane buffer size. 681 * calculating plane buffer size.
679 */ 682 */
680typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width, 683typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width,
681 uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, 684 uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v,
682 int32_t ystride, int32_t ustride, int32_t vstride, void *user_data); 685 int32_t ystride, int32_t ustride, int32_t vstride, void *user_data);
683 686
684/** 687/**
685 * Set the callback for the `video_receive_frame` event. Pass NULL to unset. 688 * 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_
700 * 703 *
701 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)). 704 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
702 */ 705 */
703int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void*, int, int, const int16_t *, unsigned int, uint8_t, 706int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, int, int, const int16_t *, unsigned int, uint8_t,
704 unsigned int, void *), void *userdata); 707 unsigned int, void *), void *userdata);
705 708
706/* Join a AV group (you need to have been invited first.) 709/* 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
714 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)). 717 * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)).
715 */ 718 */
716int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length, 719int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length,
717 void (*audio_callback)(void*, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata); 720 void (*audio_callback)(void *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int, void *), void *userdata);
718 721
719/* Send audio to the group chat. 722/* Send audio to the group chat.
720 * 723 *
diff --git a/toxav/video.c b/toxav/video.c
index acc1852b..8a832201 100644
--- a/toxav/video.c
+++ b/toxav/video.c
@@ -207,43 +207,40 @@ int vc_queue_message(void *vcp, struct RTPMessage *msg)
207 207
208 return 0; 208 return 0;
209} 209}
210int vc_reconfigure_encoder(VCSession* vc, uint32_t bit_rate, uint16_t width, uint16_t height) 210int vc_reconfigure_encoder(VCSession *vc, uint32_t bit_rate, uint16_t width, uint16_t height)
211{ 211{
212 if (!vc) 212 if (!vc)
213 return -1; 213 return -1;
214 214
215 vpx_codec_enc_cfg_t cfg = *vc->encoder->config.enc; 215 vpx_codec_enc_cfg_t cfg = *vc->encoder->config.enc;
216 int rc; 216 int rc;
217 217
218 if (cfg.rc_target_bitrate == bit_rate && cfg.g_w == width && cfg.g_h == height) 218 if (cfg.rc_target_bitrate == bit_rate && cfg.g_w == width && cfg.g_h == height)
219 return 0; /* Nothing changed */ 219 return 0; /* Nothing changed */
220 220
221 if (cfg.g_w == width && cfg.g_h == height) 221 if (cfg.g_w == width && cfg.g_h == height) {
222 {
223 /* Only bit rate changed */ 222 /* Only bit rate changed */
224 cfg.rc_target_bitrate = bit_rate; 223 cfg.rc_target_bitrate = bit_rate;
225 224
226 rc = vpx_codec_enc_config_set(vc->encoder, &cfg); 225 rc = vpx_codec_enc_config_set(vc->encoder, &cfg);
227 226
228 if (rc != VPX_CODEC_OK) { 227 if (rc != VPX_CODEC_OK) {
229 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); 228 LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
230 return -1; 229 return -1;
231 } 230 }
232 } 231 } else {
233 else
234 {
235 /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support 232 /* Resolution is changed, must reinitialize encoder since libvpx v1.4 doesn't support
236 * reconfiguring encoder to use resolutions greater than initially set. 233 * reconfiguring encoder to use resolutions greater than initially set.
237 */ 234 */
238 235
239 LOGGER_DEBUG("Have to reinitialize vpx encoder on session %p", vc); 236 LOGGER_DEBUG("Have to reinitialize vpx encoder on session %p", vc);
240 237
241 cfg.rc_target_bitrate = bit_rate; 238 cfg.rc_target_bitrate = bit_rate;
242 cfg.g_w = width; 239 cfg.g_w = width;
243 cfg.g_h = height; 240 cfg.g_h = height;
244 241
245 vpx_codec_ctx_t new_c; 242 vpx_codec_ctx_t new_c;
246 243
247 rc = vpx_codec_enc_init(&new_c, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); 244 rc = vpx_codec_enc_init(&new_c, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
248 245
249 if (rc != VPX_CODEC_OK) { 246 if (rc != VPX_CODEC_OK) {
@@ -258,7 +255,7 @@ int vc_reconfigure_encoder(VCSession* vc, uint32_t bit_rate, uint16_t width, uin
258 vpx_codec_destroy(&new_c); 255 vpx_codec_destroy(&new_c);
259 return -1; 256 return -1;
260 } 257 }
261 258
262 vpx_codec_destroy(vc->encoder); 259 vpx_codec_destroy(vc->encoder);
263 memcpy(vc->encoder, &new_c, sizeof(new_c)); 260 memcpy(vc->encoder, &new_c, sizeof(new_c));
264 } 261 }
diff --git a/toxav/video.h b/toxav/video.h
index 51f34318..fb836a35 100644
--- a/toxav/video.h
+++ b/toxav/video.h
@@ -58,7 +58,7 @@ typedef struct VCSession_s {
58 pthread_mutex_t queue_mutex[1]; 58 pthread_mutex_t queue_mutex[1];
59} VCSession; 59} VCSession;
60 60
61VCSession *vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb* cb, void* cb_data); 61VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data);
62void vc_kill(VCSession *vc); 62void vc_kill(VCSession *vc);
63void vc_iterate(VCSession *vc); 63void vc_iterate(VCSession *vc);
64int vc_queue_message(void *vcp, struct RTPMessage *msg); 64int vc_queue_message(void *vcp, struct RTPMessage *msg);