diff options
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/audio.c | 10 | ||||
-rw-r--r-- | toxav/bwcontroler.c | 62 | ||||
-rw-r--r-- | toxav/msi.c | 79 | ||||
-rw-r--r-- | toxav/rtp.c | 27 | ||||
-rw-r--r-- | toxav/toxav.c | 57 | ||||
-rw-r--r-- | toxav/toxav.h | 541 | ||||
-rw-r--r-- | toxav/video.c | 23 | ||||
-rw-r--r-- | toxav/video.h | 2 |
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 | } |
222 | int ac_reconfigure_encoder(ACSession *ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels) | 222 | int 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 | ||
40 | struct BWControler_s { | 40 | struct 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 | } |
97 | void bwc_feed_avg(BWControler* bwc, uint32_t bytes) | 98 | void 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 | } |
106 | void bwc_add_lost(BWControler *bwc, uint32_t bytes) | 107 | void 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 { | |||
145 | void send_update(BWControler *bwc) | 147 | void 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 | } |
174 | int on_update (BWControler *bwc, struct BWCMessage *msg) | 174 | int 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 | } |
198 | int bwc_handle_data(Messenger* m, uint32_t friendnumber, const uint8_t* data, uint16_t length, void* object) | 198 | int 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 | } |
622 | void handle_init (MSICall* call, const MSIMessage* msg) | 622 | void 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; |
678 | FAILURE: | 677 | FAILURE: |
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 | } |
215 | Tox *toxav_get_tox(const ToxAV *av) | 215 | Tox *toxav_get_tox(const ToxAV *av) |
@@ -277,11 +277,11 @@ bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint | |||
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 | ||
312 | END: | 312 | END: |
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); |
631 | END: | 642 | END: |
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 | ||
721 | END: | 733 | END: |
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 | ||
819 | END: | 832 | END: |
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 | ******************************************************************************/ |
846 | void callback_bwc(BWControler* bwc, uint32_t friend_number, float loss, void* user_data) | 860 | void 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 | } |
881 | int callback_invite(void *toxav_inst, MSICall *call) | 896 | int 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 | ******************************************************************************/ |
171 | typedef enum TOXAV_ERR_NEW { | 171 | typedef 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 | */ |
227 | void toxav_iterate(ToxAV *toxAV); | 227 | void toxav_iterate(ToxAV *toxAV); |
228 | 228 | ||
229 | 229 | ||
230 | /******************************************************************************* | 230 | /******************************************************************************* |
231 | * | 231 | * |
232 | * :: Call setup | 232 | * :: Call setup |
233 | * | 233 | * |
234 | ******************************************************************************/ | 234 | ******************************************************************************/ |
235 | typedef enum TOXAV_ERR_CALL { | 235 | typedef 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 | |||
299 | void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data); | 299 | void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data); |
300 | 300 | ||
301 | typedef enum TOXAV_ERR_ANSWER { | 301 | typedef 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 | */ |
344 | bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error); | 344 | bool 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 | ******************************************************************************/ |
352 | enum TOXAV_FRIEND_CALL_STATE { | 353 | enum 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 | |||
399 | void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data); | 400 | void 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 | ******************************************************************************/ |
406 | typedef enum TOXAV_CALL_CONTROL { | 407 | typedef 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 | ||
443 | typedef enum TOXAV_ERR_CALL_CONTROL { | 444 | typedef 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 | */ |
477 | bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error); | 478 | bool 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 | ******************************************************************************/ |
485 | typedef enum TOXAV_ERR_BIT_RATE_SET { | 487 | typedef 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 | */ |
523 | bool toxav_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, int32_t audio_bit_rate, | 525 | bool 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 | */ |
536 | typedef void toxav_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, void *user_data); | 538 | typedef 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 | ******************************************************************************/ |
550 | typedef enum TOXAV_ERR_SEND_FRAME { | 553 | typedef 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 | */ |
608 | bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, | 611 | bool 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 | */ |
627 | bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width, | 630 | bool 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 | */ |
649 | typedef void toxav_audio_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, | 652 | typedef 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 | */ |
680 | typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width, | 683 | typedef 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 | */ |
703 | int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void*, int, int, const int16_t *, unsigned int, uint8_t, | 706 | int 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 | */ |
716 | int toxav_join_av_groupchat(Tox *tox, int32_t friendnumber, const uint8_t *data, uint16_t length, | 719 | int 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 | } |
210 | int vc_reconfigure_encoder(VCSession* vc, uint32_t bit_rate, uint16_t width, uint16_t height) | 210 | int 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 | ||
61 | VCSession *vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb* cb, void* cb_data); | 61 | VCSession *vc_new(ToxAV *av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data); |
62 | void vc_kill(VCSession *vc); | 62 | void vc_kill(VCSession *vc); |
63 | void vc_iterate(VCSession *vc); | 63 | void vc_iterate(VCSession *vc); |
64 | int vc_queue_message(void *vcp, struct RTPMessage *msg); | 64 | int vc_queue_message(void *vcp, struct RTPMessage *msg); |