summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-04-29 01:01:25 +0200
committermannol <eniz_vukovic@hotmail.com>2015-04-29 01:01:25 +0200
commit9bba7a0434d0967d5dd76b8afc7783ea2edad0cf (patch)
tree6486c250acb38429a63a62e54cd1e4bcb0a029ee
parente4a020333d76bc30172f54f2545677f01bdd54b6 (diff)
Done
-rw-r--r--auto_tests/Makefile.inc10
-rw-r--r--auto_tests/toxav_basic_test.c875
-rw-r--r--auto_tests/toxav_many_test.c459
-rw-r--r--testing/av_test.c (renamed from toxav/av_test.c)264
-rw-r--r--toxav/Makefile.inc21
-rw-r--r--toxav/audio.c35
-rw-r--r--toxav/audio.h33
-rw-r--r--toxav/msi.c124
-rw-r--r--toxav/msi.h24
-rw-r--r--toxav/rtp.c67
-rw-r--r--toxav/rtp.h11
-rw-r--r--toxav/toxav.c132
-rw-r--r--toxav/toxav.h40
-rw-r--r--toxav/video.c25
-rw-r--r--toxav/video.h36
15 files changed, 764 insertions, 1392 deletions
diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc
index d78a6a5a..741ca7fa 100644
--- a/auto_tests/Makefile.inc
+++ b/auto_tests/Makefile.inc
@@ -21,8 +21,8 @@ AUTOTEST_LDADD = \
21 21
22 22
23if BUILD_AV 23if BUILD_AV
24TESTS += toxav_basic_test toxav_many_test 24TESTS += toxav_basic_test #toxav_many_test
25check_PROGRAMS += toxav_basic_test toxav_many_test 25check_PROGRAMS += toxav_basic_test #toxav_many_test
26AUTOTEST_LDADD += libtoxav.la 26AUTOTEST_LDADD += libtoxav.la
27endif 27endif
28 28
@@ -90,11 +90,11 @@ toxav_basic_test_CFLAGS = $(AUTOTEST_CFLAGS)
90toxav_basic_test_LDADD = $(AUTOTEST_LDADD) $(AV_LIBS) 90toxav_basic_test_LDADD = $(AUTOTEST_LDADD) $(AV_LIBS)
91 91
92 92
93toxav_many_test_SOURCES = ../auto_tests/toxav_many_test.c 93#toxav_many_test_SOURCES = ../auto_tests/toxav_many_test.c
94 94
95toxav_many_test_CFLAGS = $(AUTOTEST_CFLAGS) 95#toxav_many_test_CFLAGS = $(AUTOTEST_CFLAGS)
96 96
97toxav_many_test_LDADD = $(AUTOTEST_LDADD) 97#toxav_many_test_LDADD = $(AUTOTEST_LDADD)
98endif 98endif
99 99
100endif 100endif
diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c
index a43b7c2f..7598c0db 100644
--- a/auto_tests/toxav_basic_test.c
+++ b/auto_tests/toxav_basic_test.c
@@ -14,6 +14,7 @@
14#include <vpx/vpx_image.h> 14#include <vpx/vpx_image.h>
15 15
16#include "../toxcore/tox.h" 16#include "../toxcore/tox.h"
17#include "../toxcore/util.h"
17#include "../toxcore/logger.h" 18#include "../toxcore/logger.h"
18#include "../toxcore/crypto_core.h" 19#include "../toxcore/crypto_core.h"
19#include "../toxav/toxav.h" 20#include "../toxav/toxav.h"
@@ -28,600 +29,406 @@
28#endif 29#endif
29 30
30 31
32#define TEST_REGULAR_AV 1
33#define TEST_REGULAR_A 1
34#define TEST_REGULAR_V 1
35#define TEST_REJECT 1
36#define TEST_CANCEL 1
37#define TEST_MUTE_UNMUTE 1
31 38
32typedef enum _CallStatus {
33 none,
34 InCall,
35 Ringing,
36 Ended,
37 Rejected,
38 Canceled,
39 TimedOut
40 39
41} CallStatus; 40typedef struct {
41 bool incoming;
42 uint32_t state;
43
44} CallControl;
42 45
43typedef struct _Party {
44 CallStatus status;
45 ToxAv *av;
46 time_t *CallStarted;
47 int call_index;
48} Party;
49 46
50typedef struct _Status { 47/**
51 Party Alice; 48 * Callbacks
52 Party Bob; 49 */
53} Status; 50void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data)
54
55/* My default settings */
56static ToxAvCSettings muhcaps;
57
58void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
59{
60 if (length == 7 && memcmp("gentoo", data, 7) == 0) {
61 tox_friend_add_norequest(m, public_key, 0);
62 }
63}
64
65
66/******************************************************************************/
67void callback_recv_invite ( void *av, int32_t call_index, void *_arg )
68{
69 Status *cast = _arg;
70
71 if (cast->Alice.av == av) {
72 // ...
73 } else if (cast->Bob.av == av) {
74 /* Bob always receives invite */
75 cast->Bob.status = Ringing;
76 cast->Bob.call_index = call_index;
77 }
78}
79void callback_recv_ringing ( void *av, int32_t call_index, void *_arg )
80{
81 Status *cast = _arg;
82
83 if (cast->Alice.av == av) {
84 /* Alice always sends invite */
85 cast->Alice.status = Ringing;
86 } else if (cast->Bob.av == av) {
87 // ...
88 }
89}
90
91
92void callback_call_started ( void *av, int32_t call_index, void *_arg )
93{
94 Status *cast = _arg;
95
96 if (cast->Alice.av == av) {
97 printf("Call started on Alices side...\n");
98 cast->Alice.status = InCall;
99 toxav_prepare_transmission(av, call_index, 1);
100 } else if (cast->Bob.av == av) {
101 printf("Call started on Bob side...\n");
102 cast->Bob.status = InCall;
103 toxav_prepare_transmission(av, call_index, 1);
104 }
105}
106void callback_call_canceled ( void *av, int32_t call_index, void *_arg )
107{ 51{
108 Status *cast = _arg; 52 printf("Handling CALL callback\n");
109 53 ((CallControl*)user_data)->incoming = true;
110 if (cast->Alice.av == av) {
111 // ...
112 } else if (cast->Bob.av == av) {
113 printf ( "Call Canceled for Bob!\n" );
114 cast->Bob.status = Canceled;
115 }
116} 54}
117void callback_call_rejected ( void *av, int32_t call_index, void *_arg ) 55void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data)
118{ 56{
119 Status *cast = _arg; 57 printf("Handling CALL STATE callback: %d\n", state);
120 58 ((CallControl*)user_data)->state = state;
121 printf ( "Call rejected by Bob!\n"
122 "Call ended for Alice!\n" );
123
124 /* If Bob rejects, call is ended for alice and she sends ending */
125 if (cast->Alice.av == av) {
126 cast->Alice.status = Rejected;
127 } else if (cast->Bob.av == av) {
128 //... ignor
129 }
130} 59}
131void callback_call_ended ( void *av, int32_t call_index, void *_arg ) 60void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
61 uint16_t width, uint16_t height,
62 uint8_t const *y, uint8_t const *u, uint8_t const *v,
63 int32_t ystride, int32_t ustride, int32_t vstride,
64 void *user_data)
132{ 65{
133 Status *cast = _arg; 66 (void) av;
134 67 (void) friend_number;
135 if (cast->Alice.av == av) { 68 (void) width;
136 printf ( "Call ended for Alice!\n" ); 69 (void) height;
137 cast->Alice.status = Ended; 70 (void) y;
138 } else if (cast->Bob.av == av) { 71 (void) u;
139 printf ( "Call ended for Bob!\n" ); 72 (void) v;
140 cast->Bob.status = Ended; 73 (void) ystride;
141 } 74 (void) ustride;
75 (void) vstride;
76 (void) user_data;
142} 77}
143 78void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
144void callback_peer_cs_change ( void *av, int32_t call_index, void *_arg ) 79 int16_t const *pcm,
80 size_t sample_count,
81 uint8_t channels,
82 uint32_t sampling_rate,
83 void *user_data)
145{ 84{
146 ToxAvCSettings csettings; 85 (void) av;
147 toxav_get_peer_csettings(av, call_index, 0, &csettings); 86 (void) friend_number;
148 87 (void) pcm;
149 printf("Peer changing settings to: \n" 88 (void) sample_count;
150 "Type: %u \n" 89 (void) channels;
151 "Video bitrate: %u \n" 90 (void) sampling_rate;
152 "Video height: %u \n" 91 (void) user_data;
153 "Video width: %u \n"
154 "Audio bitrate: %u \n"
155 "Audio framedur: %u \n"
156 "Audio sample rate: %u \n"
157 "Audio channels: %u \n",
158 csettings.call_type,
159 csettings.video_bitrate,
160 csettings.max_video_height,
161 csettings.max_video_width,
162 csettings.audio_bitrate,
163 csettings.audio_frame_duration,
164 csettings.audio_sample_rate,
165 csettings.audio_channels
166 );
167} 92}
168 93void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
169void callback_self_cs_change ( void *av, int32_t call_index, void *_arg )
170{ 94{
171 ToxAvCSettings csettings; 95 if (length == 7 && memcmp("gentoo", data, 7) == 0) {
172 toxav_get_peer_csettings(av, call_index, 0, &csettings); 96 assert(tox_friend_add_norequest(m, public_key, NULL) != (uint32_t) ~0);
173
174 printf("Changed settings to: \n"
175 "Type: %u \n"
176 "Video bitrate: %u \n"
177 "Video height: %u \n"
178 "Video width: %u \n"
179 "Audio bitrate: %u \n"
180 "Audio framedur: %u \n"
181 "Audio sample rate: %u \n"
182 "Audio channels: %u \n",
183 csettings.call_type,
184 csettings.video_bitrate,
185 csettings.max_video_height,
186 csettings.max_video_width,
187 csettings.audio_bitrate,
188 csettings.audio_frame_duration,
189 csettings.audio_sample_rate,
190 csettings.audio_channels
191 );
192}
193
194void callback_requ_timeout ( void *av, int32_t call_index, void *_arg )
195{
196 Status *cast = _arg;
197 printf("Call timed-out!\n");
198
199 if (cast->Alice.av == av) {
200 cast->Alice.status = TimedOut;
201 } else if (cast->Bob.av == av) {
202 cast->Bob.status = TimedOut;
203 } 97 }
204} 98}
205 99
206void callback_audio (void *agent, int32_t call_idx, const int16_t *PCM, uint16_t size, void *data)
207{}
208
209void callback_video (void *agent, int32_t call_idx, const vpx_image_t *img, void *data)
210{}
211 100
212void register_callbacks(ToxAv *av, void *data) 101/**
102 * Iterate helper
103 */
104int iterate_tox(Tox* bootstrap, Tox* Alice, Tox* Bob)
213{ 105{
214 toxav_register_callstate_callback(av, callback_call_started, av_OnStart, data); 106 tox_iterate(bootstrap);
215 toxav_register_callstate_callback(av, callback_call_canceled, av_OnCancel, data); 107 tox_iterate(Alice);
216 toxav_register_callstate_callback(av, callback_call_rejected, av_OnReject, data); 108 tox_iterate(Bob);
217 toxav_register_callstate_callback(av, callback_call_ended, av_OnEnd, data); 109
218 toxav_register_callstate_callback(av, callback_recv_invite, av_OnInvite, data); 110 return MIN(tox_iteration_interval(Alice), tox_iteration_interval(Bob));
219 toxav_register_callstate_callback(av, callback_recv_ringing, av_OnRinging, data);
220 toxav_register_callstate_callback(av, callback_requ_timeout, av_OnRequestTimeout, data);
221 toxav_register_callstate_callback(av, callback_peer_cs_change, av_OnPeerCSChange, data);
222 toxav_register_callstate_callback(av, callback_self_cs_change, av_OnSelfCSChange, data);
223 toxav_register_audio_callback(av, callback_audio, NULL);
224 toxav_register_video_callback(av, callback_video, NULL);
225} 111}
226 112
227 113
228/*************************************************************************************************/
229
230/* Alice calls bob and the call starts.
231 * What happens during the call is defined after. To quit the loop use: step++;
232 */
233#define CALL_AND_START_LOOP(AliceCallType, BobCallType) \
234{ int step = 0, running = 1; while (running) {\
235 tox_iterate(bootstrap_node); tox_iterate(Alice); tox_iterate(Bob); \
236 toxav_do(status_control.Bob.av); toxav_do(status_control.Alice.av); \
237 switch ( step ) {\
238 case 0: /* Alice */ printf("Alice is calling...\n");\
239 toxav_call(status_control.Alice.av, &status_control.Alice.call_index, 0, &muhcaps, 10); step++; break;\
240 case 1: /* Bob */ if (status_control.Bob.status == Ringing) { printf("Bob answers...\n");\
241 cur_time = time(NULL); toxav_answer(status_control.Bob.av, status_control.Bob.call_index, &muhcaps); step++; } break; \
242 case 2: /* Rtp transmission */ \
243 if (status_control.Bob.status == InCall && status_control.Alice.status == InCall)
244
245
246#define TERMINATE_SCOPE() break;\
247case 3: /* Wait for Both to have status ended */\
248if (status_control.Alice.status == Ended && status_control.Bob.status == Ended) running = 0; break; } c_sleep(20); } } printf("\n");
249 114
250START_TEST(test_AV_flows) 115START_TEST(test_AV_flows)
251{ 116{
117 Tox* Alice, *Bob, *bootstrap;
118 ToxAV* AliceAV, *BobAV;
119
120 CallControl AliceCC, BobCC;
121
122 {
123 TOX_ERR_NEW error;
124
125 bootstrap = tox_new(NULL, NULL, 0, &error);
126 assert(error == TOX_ERR_NEW_OK);
127
128 Alice = tox_new(NULL, NULL, 0, &error);
129 assert(error == TOX_ERR_NEW_OK);
130
131 Bob = tox_new(NULL, NULL, 0, &error);
132 assert(error == TOX_ERR_NEW_OK);
133 }
134
135 printf("Created 3 instances of Tox\n");
136 printf("Preparing network...\n");
252 long long unsigned int cur_time = time(NULL); 137 long long unsigned int cur_time = time(NULL);
253 Tox *bootstrap_node = tox_new(0, 0, 0, 0); 138
254 Tox *Alice = tox_new(0, 0, 0, 0);
255 Tox *Bob = tox_new(0, 0, 0, 0);
256
257 ck_assert_msg(bootstrap_node || Alice || Bob, "Failed to create 3 tox instances");
258
259 uint32_t to_compare = 974536; 139 uint32_t to_compare = 974536;
260 tox_callback_friend_request(Alice, accept_friend_request, &to_compare);
261 uint8_t address[TOX_ADDRESS_SIZE]; 140 uint8_t address[TOX_ADDRESS_SIZE];
141
142 tox_callback_friend_request(Alice, t_accept_friend_request_cb, &to_compare);
262 tox_self_get_address(Alice, address); 143 tox_self_get_address(Alice, address);
263 uint32_t test = tox_friend_add(Bob, address, (uint8_t *)"gentoo", 7, 0); 144
264 145
265 ck_assert_msg(test == 0, "Failed to add friend error code: %i", test); 146 assert(tox_friend_add(Bob, address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0);
266 147
267 uint8_t off = 1; 148 uint8_t off = 1;
268 149
269 while (1) { 150 while (1) {
270 tox_iterate(bootstrap_node); 151 iterate_tox(bootstrap, Alice, Bob);
271 tox_iterate(Alice); 152
272 tox_iterate(Bob); 153 if (tox_self_get_connection_status(bootstrap) &&
273 154 tox_self_get_connection_status(Alice) &&
274 if (tox_self_get_connection_status(bootstrap_node) && tox_self_get_connection_status(Alice) 155 tox_self_get_connection_status(Bob) && off) {
275 && tox_self_get_connection_status(Bob)
276 && off) {
277 printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); 156 printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time);
278 off = 0; 157 off = 0;
279 } 158 }
280 159
281 if (tox_friend_get_connection_status(Alice, 0, 0) && tox_friend_get_connection_status(Bob, 0, 0)) 160 if (tox_friend_get_connection_status(Alice, 0, NULL) == TOX_CONNECTION_UDP &&
161 tox_friend_get_connection_status(Bob, 0, NULL) == TOX_CONNECTION_UDP)
282 break; 162 break;
283 163
284 c_sleep(20); 164 c_sleep(20);
285 } 165 }
286 166
287 printf("All set after %llu seconds! Starting call...\n", time(NULL) - cur_time); 167
288 168 {
289 muhcaps = av_DefaultSettings; 169 TOXAV_ERR_NEW error;
290 muhcaps.max_video_height = muhcaps.max_video_width = 128; 170 AliceAV = toxav_new(Alice, &error);
291 171 assert(error == TOXAV_ERR_NEW_OK);
292 Status status_control = { 172
293 {none, toxav_new(Alice, 1), NULL, -1}, 173 BobAV = toxav_new(Bob, &error);
294 {none, toxav_new(Bob, 1), NULL, -1}, 174 assert(error == TOXAV_ERR_NEW_OK);
295 };
296
297 ck_assert_msg(status_control.Alice.av || status_control.Bob.av, "Failed to create 2 toxav instances");
298
299
300 register_callbacks(status_control.Alice.av, &status_control);
301 register_callbacks(status_control.Bob.av, &status_control);
302
303 const int frame_size = (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000);
304 int16_t sample_payload[frame_size];
305 randombytes((uint8_t *)sample_payload, sizeof(int16_t) * frame_size);
306
307 uint8_t prepared_payload[RTP_PAYLOAD_SIZE];
308 int payload_size;
309
310 vpx_image_t *sample_image = vpx_img_alloc(NULL, VPX_IMG_FMT_I420, 128, 128, 1);
311
312 memcpy(sample_image->planes[VPX_PLANE_Y], sample_payload, 10);
313 memcpy(sample_image->planes[VPX_PLANE_U], sample_payload, 10);
314 memcpy(sample_image->planes[VPX_PLANE_V], sample_payload, 10);
315
316
317 /*************************************************************************************************
318 * Successful flows (when call starts)
319 */
320
321 /*
322 * Call with audio only on both sides. Alice calls Bob.
323 */
324
325
326 CALL_AND_START_LOOP(TypeAudio, TypeAudio) {
327 /* Both send */
328 payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload,
329 1000, sample_payload, frame_size);
330
331 if ( payload_size < 0 ) {
332 ck_assert_msg ( 0, "Failed to encode payload" );
333 }
334
335 toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size);
336
337 payload_size = toxav_prepare_audio_frame(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, 1000,
338 sample_payload, frame_size);
339
340 if ( payload_size < 0 ) {
341 ck_assert_msg ( 0, "Failed to encode payload" );
342 }
343
344 toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size);
345
346 if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */
347 step++; /* This terminates the loop */
348 toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index);
349 toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index);
350
351 /* Call over Alice hangs up */
352 toxav_hangup(status_control.Alice.av, status_control.Alice.call_index);
353 }
354 } 175 }
355 TERMINATE_SCOPE() 176
356 177 toxav_callback_call(AliceAV, t_toxav_call_cb, &AliceCC);
357 178 toxav_callback_call_state(AliceAV, t_toxav_call_state_cb, &AliceCC);
358 /* 179 toxav_callback_receive_video_frame(AliceAV, t_toxav_receive_video_frame_cb, &AliceCC);
359 * Call with audio on both sides and video on one side. Alice calls Bob. 180 toxav_callback_receive_audio_frame(AliceAV, t_toxav_receive_audio_frame_cb, &AliceCC);
360 */ 181
361 CALL_AND_START_LOOP(TypeAudio, TypeVideo) { 182 toxav_callback_call(BobAV, t_toxav_call_cb, &BobCC);
362 /* Both send */ 183 toxav_callback_call_state(BobAV, t_toxav_call_state_cb, &BobCC);
363 payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, 184 toxav_callback_receive_video_frame(BobAV, t_toxav_receive_video_frame_cb, &BobCC);
364 1000, sample_payload, frame_size); 185 toxav_callback_receive_audio_frame(BobAV, t_toxav_receive_audio_frame_cb, &BobCC);
365 186
366 if ( payload_size < 0 ) { 187 printf("Created 2 instances of ToxAV\n");
367 ck_assert_msg ( 0, "Failed to encode payload" ); 188 printf("All set after %llu seconds!\n", time(NULL) - cur_time);
368 } 189
369 190
370 toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size); 191#define REGULAR_CALL_FLOW(A_BR, V_BR) \
371 192 do { \
372 payload_size = toxav_prepare_audio_frame(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, 1000, 193 memset(&AliceCC, 0, sizeof(CallControl)); \
373 sample_payload, frame_size); 194 memset(&BobCC, 0, sizeof(CallControl)); \
374 195 \
375 if ( payload_size < 0 ) { 196 TOXAV_ERR_CALL rc; \
376 ck_assert_msg ( 0, "Failed to encode payload" ); 197 toxav_call(AliceAV, 0, A_BR, V_BR, &rc); \
377 } 198 \
378 199 if (rc != TOXAV_ERR_CALL_OK) { \
379 toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size); 200 printf("toxav_call failed: %d\n", rc); \
380 201 exit(1); \
381// toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); 202 } \
382 203 \
383 if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ 204 \
384 step++; /* This terminates the loop */ 205 long long unsigned int start_time = time(NULL); \
385 toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index); 206 \
386 toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index); 207 \
387 208 while (BobCC.state != TOXAV_CALL_STATE_END) { \
388 /* Call over Alice hangs up */ 209 \
389 toxav_hangup(status_control.Alice.av, status_control.Alice.call_index); 210 if (BobCC.incoming) { \
390 } 211 TOXAV_ERR_ANSWER rc; \
212 toxav_answer(BobAV, 0, A_BR, V_BR, &rc); \
213 \
214 if (rc != TOXAV_ERR_ANSWER_OK) { \
215 printf("toxav_answer failed: %d\n", rc); \
216 exit(1); \
217 } \
218 BobCC.incoming = false; \
219 } else { \
220 /* TODO rtp */ \
221 \
222 if (time(NULL) - start_time == 5) { \
223 \
224 TOXAV_ERR_CALL_CONTROL rc; \
225 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); \
226 \
227 if (rc != TOXAV_ERR_CALL_CONTROL_OK) { \
228 printf("toxav_call_control failed: %d\n", rc); \
229 exit(1); \
230 } \
231 } \
232 } \
233 \
234 iterate_tox(bootstrap, Alice, Bob); \
235 } \
236 printf("Success!\n");\
237 } while(0)
238
239 if (TEST_REGULAR_AV) {
240 printf("\nTrying regular call (Audio and Video)...\n");
241 REGULAR_CALL_FLOW(48, 4000);
391 } 242 }
392 TERMINATE_SCOPE() 243
393 244 if (TEST_REGULAR_A) {
394 245 printf("\nTrying regular call (Audio only)...\n");
395 /* 246 REGULAR_CALL_FLOW(48, 0);
396 * Call with audio and video on both sides. Alice calls Bob.
397 */
398 CALL_AND_START_LOOP(TypeVideo, TypeVideo) {
399 /* Both send */
400
401 payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload,
402 1000, sample_payload, frame_size);
403
404 if ( payload_size < 0 ) {
405 ck_assert_msg ( 0, "Failed to encode payload" );
406 }
407
408 toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size);
409
410 payload_size = toxav_prepare_audio_frame(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, 1000,
411 sample_payload, frame_size);
412
413 if ( payload_size < 0 ) {
414 ck_assert_msg ( 0, "Failed to encode payload" );
415 }
416
417 toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size);
418
419// toxav_send_video(status_control.Alice.av, status_control.Alice.call_index, sample_image);
420// toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image);
421
422
423 if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */
424 step++; /* This terminates the loop */
425 toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index);
426 toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index);
427
428 /* Call over Alice hangs up */
429 toxav_hangup(status_control.Alice.av, status_control.Alice.call_index);
430 }
431 } 247 }
432 TERMINATE_SCOPE() 248
433 249 if (TEST_REGULAR_V) {
434 250 printf("\nTrying regular call (Video only)...\n");
435 uint64_t times_they_are_a_changin = time(NULL); 251 REGULAR_CALL_FLOW(0, 4000);
436 /* Media change */ 252 }
437 CALL_AND_START_LOOP(TypeAudio, TypeAudio) { 253
438 /* Both send */ 254#undef REGULAR_CALL_FLOW
439 payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, 255
440 1000, sample_payload, frame_size); 256 if (TEST_REJECT) { /* Alice calls; Bob rejects */
441 257 printf("\nTrying reject flow...\n");
442 if ( payload_size < 0 ) { 258
443 ck_assert_msg ( 0, "Failed to encode payload" ); 259 memset(&AliceCC, 0, sizeof(CallControl));
260 memset(&BobCC, 0, sizeof(CallControl));
261
262 {
263 TOXAV_ERR_CALL rc;
264 toxav_call(AliceAV, 0, 48, 0, &rc);
265
266 if (rc != TOXAV_ERR_CALL_OK) {
267 printf("toxav_call failed: %d\n", rc);
268 exit(1);
269 }
444 } 270 }
445 271
446 toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size); 272 while (!BobCC.incoming)
447 273 iterate_tox(bootstrap, Alice, Bob);
448 payload_size = toxav_prepare_audio_frame(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, 1000, 274
449 sample_payload, frame_size); 275 /* Reject */
450 276 {
451 if ( payload_size < 0 ) { 277 TOXAV_ERR_CALL_CONTROL rc;
452 ck_assert_msg ( 0, "Failed to encode payload" ); 278 toxav_call_control(BobAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
279
280 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
281 printf("toxav_call_control failed: %d\n", rc);
282 exit(1);
283 }
453 } 284 }
454 285
455 toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size); 286 while (AliceCC.state != TOXAV_CALL_STATE_END)
456 287 iterate_tox(bootstrap, Alice, Bob);
457 /* Wait 2 seconds and change transmission type */ 288
458 if (time(NULL) - times_they_are_a_changin > 2) { 289 printf("Success!\n");
459 times_they_are_a_changin = time(NULL); 290 }
460 muhcaps.audio_bitrate ++; 291
461 toxav_change_settings(status_control.Alice.av, status_control.Alice.call_index, &muhcaps); 292 if (TEST_CANCEL) { /* Alice calls; Alice cancels while ringing */
293 printf("\nTrying cancel (while ringing) flow...\n");
294
295 memset(&AliceCC, 0, sizeof(CallControl));
296 memset(&BobCC, 0, sizeof(CallControl));
297
298 {
299 TOXAV_ERR_CALL rc;
300 toxav_call(AliceAV, 0, 48, 0, &rc);
301
302 if (rc != TOXAV_ERR_CALL_OK) {
303 printf("toxav_call failed: %d\n", rc);
304 exit(1);
305 }
462 } 306 }
463 307
464 if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ 308 while (!BobCC.incoming)
465 step++; /* This terminates the loop */ 309 iterate_tox(bootstrap, Alice, Bob);
466 toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index); 310
467 toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index); 311 /* Cancel */
468 312 {
469 /* Call over Alice hangs up */ 313 TOXAV_ERR_CALL_CONTROL rc;
470 toxav_hangup(status_control.Alice.av, status_control.Alice.call_index); 314 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
315
316 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
317 printf("toxav_call_control failed: %d\n", rc);
318 exit(1);
319 }
471 } 320 }
321
322 /* Alice will not receive end state */
323 while (BobCC.state != TOXAV_CALL_STATE_END)
324 iterate_tox(bootstrap, Alice, Bob);
325
326 printf("Success!\n");
472 } 327 }
473 TERMINATE_SCOPE() 328
474 329 if (TEST_MUTE_UNMUTE) { /* Check Mute-Unmute etc */
475 330 printf("\nTrying mute functionality...\n");
476 /************************************************************************************************* 331
477 * Other flows 332 memset(&AliceCC, 0, sizeof(CallControl));
478 */ 333 memset(&BobCC, 0, sizeof(CallControl));
479 334
480 /* 335 /* Assume sending audio and video */
481 * Call and reject 336 {
482 */ 337 TOXAV_ERR_CALL rc;
483 { 338 toxav_call(AliceAV, 0, 48, 1000, &rc);
484 int step = 0; 339
485 int running = 1; 340 if (rc != TOXAV_ERR_CALL_OK) {
486 341 printf("toxav_call failed: %d\n", rc);
487 while (running) { 342 exit(1);
488 tox_iterate(bootstrap_node);
489 tox_iterate(Alice);
490 tox_iterate(Bob);
491
492 switch ( step ) {
493 case 0: /* Alice */
494 printf("Alice is calling...\n");
495 toxav_call(status_control.Alice.av, &status_control.Alice.call_index, 0, &muhcaps, 10);
496 step++;
497 break;
498
499 case 1: /* Bob */
500 if (status_control.Bob.status == Ringing) {
501 printf("Bob rejects...\n");
502 toxav_reject(status_control.Bob.av, status_control.Bob.call_index, "Who likes D's anyway?");
503 step++;
504 }
505
506 break;
507
508 case 2: /* Wait for Both to have status ended */
509 if (status_control.Alice.status == Rejected && status_control.Bob.status == Ended) running = 0;
510
511 break;
512 } 343 }
513
514 c_sleep(20);
515 } 344 }
516 345
517 printf("\n"); 346 while (!BobCC.incoming)
518 } 347 iterate_tox(bootstrap, Alice, Bob);
519 348
520 349 /* At first try all stuff while in invalid state */
521 /* 350 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
522 * Call and cancel 351 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
523 */ 352 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
524 { 353 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL));
525 int step = 0; 354
526 int running = 1; 355 {
527 356 TOXAV_ERR_ANSWER rc;
528 while (running) { 357 toxav_answer(BobAV, 0, 48, 4000, &rc);
529 tox_iterate(bootstrap_node); 358
530 tox_iterate(Alice); 359 if (rc != TOXAV_ERR_ANSWER_OK) {
531 tox_iterate(Bob); 360 printf("toxav_answer failed: %d\n", rc);
532 361 exit(1);
533 toxav_do(status_control.Alice.av);
534 toxav_do(status_control.Bob.av);
535
536
537 switch ( step ) {
538 case 0: /* Alice */
539 printf("Alice is calling...\n");
540 toxav_call(status_control.Alice.av, &status_control.Alice.call_index, 0, &muhcaps, 10);
541 step++;
542 break;
543
544
545 case 1: /* Alice again */
546 if (status_control.Bob.status == Ringing) {
547 printf("Alice cancels...\n");
548 toxav_cancel(status_control.Alice.av, status_control.Alice.call_index, 0, "Who likes D's anyway?");
549 step++;
550 }
551
552 break;
553
554 case 2: /* Wait for Both to have status ended */
555 if (status_control.Bob.status == Canceled) running = 0;
556
557 break;
558 } 362 }
559
560 c_sleep(20);
561 } 363 }
562 364
563 printf("\n"); 365 iterate_tox(bootstrap, Alice, Bob);
564 } 366
565 367 /* Pause and Resume */
566 /* 368 printf("Pause and Resume\n");
567 * Timeout 369 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
568 */ 370 iterate_tox(bootstrap, Alice, Bob);
569 { 371 assert(BobCC.state == TOXAV_CALL_STATE_PAUSED);
570 int step = 0; 372 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
571 int running = 1; 373 iterate_tox(bootstrap, Alice, Bob);
572 374 assert(BobCC.state & (TOXAV_CALL_STATE_SENDING_A | TOXAV_CALL_STATE_SENDING_V));
573 while (running) { 375
574 tox_iterate(bootstrap_node); 376 /* Mute/Unmute single */
575 tox_iterate(Alice); 377 printf("Mute/Unmute single\n");
576 tox_iterate(Bob); 378 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
577 379 iterate_tox(bootstrap, Alice, Bob);
578 toxav_do(status_control.Alice.av); 380 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
579 toxav_do(status_control.Bob.av); 381 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
580 382 iterate_tox(bootstrap, Alice, Bob);
581 switch ( step ) { 383 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
582 case 0: 384
583 printf("Alice is calling...\n"); 385 /* Mute/Unmute both */
584 toxav_call(status_control.Alice.av, &status_control.Alice.call_index, 0, &muhcaps, 10); 386 printf("Mute/Unmute both\n");
585 step++; 387 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
586 break; 388 iterate_tox(bootstrap, Alice, Bob);
587 389 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
588 case 1: 390 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL));
589 if (status_control.Alice.status == TimedOut) running = 0; 391 iterate_tox(bootstrap, Alice, Bob);
590 392 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_V);
591 break; 393 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
394 iterate_tox(bootstrap, Alice, Bob);
395 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
396 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL));
397 iterate_tox(bootstrap, Alice, Bob);
398 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_V);
399
400 {
401 TOXAV_ERR_CALL_CONTROL rc;
402 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
403
404 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
405 printf("toxav_call_control failed: %d\n", rc);
406 exit(1);
592 } 407 }
593
594 c_sleep(20);
595 } 408 }
596 409
597 printf("\n"); 410 iterate_tox(bootstrap, Alice, Bob);
411 assert(BobCC.state == TOXAV_CALL_STATE_END);
412
413 printf("Success!\n");
598 } 414 }
599 415
600 vpx_img_free(sample_image); 416 toxav_kill(BobAV);
601 toxav_kill(status_control.Alice.av); 417 toxav_kill(AliceAV);
602 toxav_kill(status_control.Bob.av);
603 tox_kill(bootstrap_node);
604 tox_kill(Alice);
605 tox_kill(Bob); 418 tox_kill(Bob);
606 419 tox_kill(Alice);
607 printf("Calls ended!\n"); 420 tox_kill(bootstrap);
421
422 printf("\nTest successful!\n");
608} 423}
609END_TEST 424END_TEST
610 425
611/*************************************************************************************************/
612
613
614/*************************************************************************************************/
615
616/*************************************************************************************************/
617
618 426
619Suite *tox_suite(void) 427Suite *tox_suite(void)
620{ 428{
621 Suite *s = suite_create("ToxAV"); 429 Suite *s = suite_create("ToxAV");
622 430
623 DEFTESTCASE_SLOW(AV_flows, 200); 431 DEFTESTCASE_SLOW(AV_flows, 200);
624
625 return s; 432 return s;
626} 433}
627int main(int argc, char *argv[]) 434int main(int argc, char *argv[])
@@ -637,6 +444,4 @@ int main(int argc, char *argv[])
637 srunner_free(test_runner); 444 srunner_free(test_runner);
638 445
639 return number_failed; 446 return number_failed;
640
641// return test_AV_flows();
642} 447}
diff --git a/auto_tests/toxav_many_test.c b/auto_tests/toxav_many_test.c
index 4287118f..ef59b2b2 100644
--- a/auto_tests/toxav_many_test.c
+++ b/auto_tests/toxav_many_test.c
@@ -14,6 +14,7 @@
14#include <vpx/vpx_image.h> 14#include <vpx/vpx_image.h>
15 15
16#include "../toxcore/tox.h" 16#include "../toxcore/tox.h"
17#include "../toxcore/util.h"
17#include "../toxcore/logger.h" 18#include "../toxcore/logger.h"
18#include "../toxcore/crypto_core.h" 19#include "../toxcore/crypto_core.h"
19#include "../toxav/toxav.h" 20#include "../toxav/toxav.h"
@@ -26,359 +27,177 @@
26#define c_sleep(x) usleep(1000*x) 27#define c_sleep(x) usleep(1000*x)
27#endif 28#endif
28 29
29pthread_mutex_t muhmutex;
30 30
31typedef enum _CallStatus { 31typedef struct {
32 none, 32 bool incoming;
33 InCall, 33 uint32_t state;
34 Ringing, 34
35 Ended, 35} CallControl;
36 Rejected,
37 Canceled
38 36
39} CallStatus;
40 37
41typedef struct _Party { 38/**
42 CallStatus status; 39 * Callbacks
43 ToxAv *av; 40 */
44 int id; 41void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data)
45} Party;
46
47typedef struct _ACall {
48 pthread_t tid;
49 int idx;
50
51 Party Caller;
52 Party Callee;
53} ACall;
54
55typedef struct _Status {
56 ACall calls[3]; /* Make 3 calls for this test */
57} Status;
58
59Status status_control;
60
61void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
62{
63 if (length == 7 && memcmp("gentoo", data, 7) == 0) {
64 tox_friend_add_norequest(m, public_key, 0);
65 }
66}
67
68
69/******************************************************************************/
70void callback_recv_invite ( void *av, int32_t call_index, void *_arg )
71{ 42{
72 Status *cast = _arg; 43 printf("Handling CALL callback\n");
73 cast->calls[call_index].Callee.status = Ringing; 44 ((CallControl*)user_data)->incoming = true;
74} 45}
75void callback_recv_ringing ( void *av, int32_t call_index, void *_arg ) 46void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data)
76{ 47{
77 Status *cast = _arg; 48 printf("Handling CALL STATE callback: %d\n", state);
78 cast->calls[call_index].Caller.status = Ringing; 49 ((CallControl*)user_data)->state = state;
79} 50}
80void callback_call_ended ( void *av, int32_t call_index, void *_arg ) 51void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
52 uint16_t width, uint16_t height,
53 uint8_t const *y, uint8_t const *u, uint8_t const *v,
54 int32_t ystride, int32_t ustride, int32_t vstride,
55 void *user_data)
81{ 56{
82 Status *cast = _arg; 57 (void) av;
83 58 (void) friend_number;
84 if (av == cast->calls[call_index].Caller.av) 59 (void) width;
85 cast->calls[call_index].Caller.status = Ended; 60 (void) height;
86 else 61 (void) y;
87 cast->calls[call_index].Callee.status = Ended; 62 (void) u;
63 (void) v;
64 (void) ystride;
65 (void) ustride;
66 (void) vstride;
67 (void) user_data;
88} 68}
89void callback_call_started ( void *av, int32_t call_index, void *_arg ) 69void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
70 int16_t const *pcm,
71 size_t sample_count,
72 uint8_t channels,
73 uint32_t sampling_rate,
74 void *user_data)
90{ 75{
91 Status *cast = _arg; 76 (void) av;
92 77 (void) friend_number;
93 if (av == cast->calls[call_index].Caller.av) 78 (void) pcm;
94 cast->calls[call_index].Caller.status = InCall; 79 (void) sample_count;
95 else 80 (void) channels;
96 cast->calls[call_index].Callee.status = InCall; 81 (void) sampling_rate;
82 (void) user_data;
97} 83}
98void callback_call_canceled ( void *av, int32_t call_index, void *_arg ) 84void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
99{ 85{
86 if (length == 7 && memcmp("gentoo", data, 7) == 0) {
87 assert(tox_friend_add_norequest(m, public_key, NULL) != (uint32_t) ~0);
88 }
100} 89}
101void callback_call_rejected ( void *av, int32_t call_index, void *_arg )
102{
103 Status *cast = _arg;
104 cast->calls[call_index].Caller.status = Rejected;
105}
106
107void callback_requ_timeout ( void *av, int32_t call_index, void *_arg )
108{
109 ck_assert_msg(0, "No answer!");
110}
111
112void callback_audio (void *agent, int32_t call_idx, const int16_t *PCM, uint16_t size, void *data)
113{}
114 90
115void callback_video (void *agent, int32_t call_idx, const vpx_image_t *img, void *data)
116{}
117 91
118void register_callbacks(ToxAv *av, void *data) 92/**
93 * Iterate helper
94 */
95ToxAV* setup_av_instance(Tox* tox, CallControl *CC)
119{ 96{
120 toxav_register_callstate_callback(av, callback_call_started, av_OnStart, data); 97 TOXAV_ERR_NEW error;
121 toxav_register_callstate_callback(av, callback_call_canceled, av_OnCancel, data); 98
122 toxav_register_callstate_callback(av, callback_call_rejected, av_OnReject, data); 99 ToxAV* av = toxav_new(tox, &error);
123 toxav_register_callstate_callback(av, callback_call_ended, av_OnEnd, data); 100 assert(error == TOXAV_ERR_NEW_OK);
124 toxav_register_callstate_callback(av, callback_recv_invite, av_OnInvite, data); 101
125 toxav_register_callstate_callback(av, callback_recv_ringing, av_OnRinging, data); 102 toxav_callback_call(av, t_toxav_call_cb, CC);
126 toxav_register_callstate_callback(av, callback_requ_timeout, av_OnRequestTimeout, data); 103 toxav_callback_call_state(av, t_toxav_call_state_cb, CC);
127 104 toxav_callback_receive_video_frame(av, t_toxav_receive_video_frame_cb, CC);
128 105 toxav_callback_receive_audio_frame(av, t_toxav_receive_audio_frame_cb, CC);
129 toxav_register_audio_callback(av, callback_audio, NULL); 106
130 toxav_register_video_callback(av, callback_video, NULL); 107 return av;
131} 108}
132/*************************************************************************************************/ 109void* call_thread(ToxAV* Alice, ToxAV* Bob)
133
134int call_running[3];
135
136void *in_thread_call (void *arg)
137{ 110{
138#define call_print(call, what, args...) printf("[%d] " what "\n", call, ##args)
139
140 ACall *this_call = arg;
141 uint64_t start = 0;
142 int step = 0;
143 int call_idx;
144
145 const int frame_size = (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000);
146 int16_t sample_payload[frame_size];
147 randombytes((uint8_t *)sample_payload, sizeof(int16_t) * frame_size);
148
149 uint8_t prepared_payload[RTP_PAYLOAD_SIZE];
150
151 register_callbacks(this_call->Caller.av, &status_control);
152 register_callbacks(this_call->Callee.av, arg);
153
154 /* NOTE: CALLEE WILL ALWAHYS NEED CALL_IDX == 0 */
155 pthread_mutex_lock(&muhmutex);
156
157 while (call_running[this_call->idx]) {
158
159 pthread_mutex_unlock(&muhmutex);
160
161 switch ( step ) {
162 case 0: /* CALLER */
163 toxav_call(this_call->Caller.av, &call_idx, this_call->Callee.id, &av_DefaultSettings, 10);
164 call_print(call_idx, "Calling ...");
165 step++;
166 break;
167
168 case 1: /* CALLEE */
169 pthread_mutex_lock(&muhmutex);
170
171 if (this_call->Caller.status == Ringing) {
172 call_print(call_idx, "Callee answers ...");
173 pthread_mutex_unlock(&muhmutex);
174 toxav_answer(this_call->Callee.av, 0, &av_DefaultSettings);
175 step++;
176 start = time(NULL);
177 pthread_mutex_lock(&muhmutex);
178 }
179
180 pthread_mutex_unlock(&muhmutex);
181 break;
182
183 case 2: /* Rtp transmission */
184 pthread_mutex_lock(&muhmutex);
185
186 if (this_call->Caller.status == InCall) { /* I think this is okay */
187 call_print(call_idx, "Sending rtp ...");
188 pthread_mutex_unlock(&muhmutex);
189
190 c_sleep(1000); /* We have race condition here */
191 toxav_prepare_transmission(this_call->Callee.av, 0, 1);
192 toxav_prepare_transmission(this_call->Caller.av, call_idx, 1);
193
194 int payload_size = toxav_prepare_audio_frame(this_call->Caller.av, call_idx, prepared_payload, RTP_PAYLOAD_SIZE,
195 sample_payload, frame_size);
196
197 if ( payload_size < 0 ) {
198 ck_assert_msg ( 0, "Failed to encode payload" );
199 }
200
201
202 while (time(NULL) - start < 10) { /* 10 seconds */
203 /* Both send */
204 toxav_send_audio(this_call->Caller.av, call_idx, prepared_payload, payload_size);
205
206 toxav_send_audio(this_call->Callee.av, 0, prepared_payload, payload_size);
207
208 /* Both receive */
209 int16_t storage[RTP_PAYLOAD_SIZE];
210 int recved;
211
212 c_sleep(20);
213 }
214
215 step++; /* This terminates the loop */
216
217 pthread_mutex_lock(&muhmutex);
218 toxav_kill_transmission(this_call->Callee.av, 0);
219 toxav_kill_transmission(this_call->Caller.av, call_idx);
220 pthread_mutex_unlock(&muhmutex);
221
222 /* Call over CALLER hangs up */
223 toxav_hangup(this_call->Caller.av, call_idx);
224 call_print(call_idx, "Hanging up ...");
225
226 pthread_mutex_lock(&muhmutex);
227 }
228
229 pthread_mutex_unlock(&muhmutex);
230 break;
231
232 case 3: /* Wait for Both to have status ended */
233 pthread_mutex_lock(&muhmutex);
234
235 if (this_call->Caller.status == Ended) {
236 pthread_mutex_unlock(&muhmutex);
237 c_sleep(1000); /* race condition */
238 pthread_mutex_lock(&muhmutex);
239 this_call->Callee.status = Ended;
240 call_running[this_call->idx] = 0;
241 }
242
243 pthread_mutex_unlock(&muhmutex);
244
245 break;
246
247 }
248
249 c_sleep(20);
250
251 pthread_mutex_lock(&muhmutex);
252 }
253
254 pthread_mutex_unlock(&muhmutex);
255 call_print(call_idx, "Call ended successfully!");
256 pthread_exit(NULL); 111 pthread_exit(NULL);
257} 112}
258 113
259
260
261
262
263START_TEST(test_AV_three_calls) 114START_TEST(test_AV_three_calls)
264// void test_AV_three_calls()
265{ 115{
266 long long unsigned int cur_time = time(NULL); 116 Tox* Alice, *bootstrap, *Bobs[3];
267 Tox *bootstrap_node = tox_new(0, 0, 0, 0); 117 ToxAV* AliceAV, *BobsAV[3];
268 Tox *caller = tox_new(0, 0, 0, 0); 118
269 Tox *callees[3] = { 119 CallControl AliceCC[3], BobsCC[3];
270 tox_new(0, 0, 0, 0), 120
271 tox_new(0, 0, 0, 0),
272 tox_new(0, 0, 0, 0),
273 };
274
275
276 ck_assert_msg(bootstrap_node != NULL, "Failed to create bootstrap node");
277
278 int i = 0; 121 int i = 0;
279 122 {
280 for (; i < 3; i ++) { 123 TOX_ERR_NEW error;
281 ck_assert_msg(callees[i] != NULL, "Failed to create 3 tox instances"); 124
282 } 125 bootstrap = tox_new(NULL, NULL, 0, &error);
283 126 assert(error == TOX_ERR_NEW_OK);
284 for ( i = 0; i < 3; i ++ ) { 127
285 uint32_t to_compare = 974536; 128 Alice = tox_new(NULL, NULL, 0, &error);
286 tox_callback_friend_request(callees[i], accept_friend_request, &to_compare); 129 assert(error == TOX_ERR_NEW_OK);
287 uint8_t address[TOX_ADDRESS_SIZE]; 130
288 tox_self_get_address(callees[i], address); 131 for (; i < 3; i ++) {
289 132 BobsAV[i] = tox_new(NULL, NULL, 0, &error);
290 uint32_t test = tox_friend_add(caller, address, (uint8_t *)"gentoo", 7, 0); 133 assert(error == TOX_ERR_NEW_OK);
291 ck_assert_msg( test == i, "Failed to add friend error code: %i", test); 134 }
292 } 135 }
293 136
137 printf("Created 5 instances of Tox\n");
138 printf("Preparing network...\n");
139 long long unsigned int cur_time = time(NULL);
140
141 uint32_t to_compare = 974536;
142 uint8_t address[TOX_ADDRESS_SIZE];
143
144 tox_callback_friend_request(Alice, t_accept_friend_request_cb, &to_compare);
145 tox_self_get_address(Alice, address);
146
147
148 assert(tox_friend_add(Bobs[0], address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0);
149 assert(tox_friend_add(Bobs[1], address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0);
150 assert(tox_friend_add(Bobs[2], address, (uint8_t *)"gentoo", 7, NULL) != (uint32_t) ~0);
151
294 uint8_t off = 1; 152 uint8_t off = 1;
295 153
296 while (1) { 154 while (1) {
297 tox_iterate(bootstrap_node); 155 tox_iterate(bootstrap);
298 tox_iterate(caller); 156 tox_iterate(Alice);
299 157 tox_iterate(Bobs[0]);
300 for (i = 0; i < 3; i ++) { 158 tox_iterate(Bobs[1]);
301 tox_iterate(callees[i]); 159 tox_iterate(Bobs[2]);
302 } 160
303 161 if (tox_self_get_connection_status(bootstrap) &&
304 162 tox_self_get_connection_status(Alice) &&
305 if (tox_self_get_connection_status(bootstrap_node) && 163 tox_self_get_connection_status(Bobs[0]) &&
306 tox_self_get_connection_status(caller) && 164 tox_self_get_connection_status(Bobs[1]) &&
307 tox_self_get_connection_status(callees[0]) && 165 tox_self_get_connection_status(Bobs[2]) && off) {
308 tox_self_get_connection_status(callees[1]) &&
309 tox_self_get_connection_status(callees[2]) && off) {
310 printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); 166 printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time);
311 off = 0; 167 off = 0;
312 } 168 }
313 169
314 170 if (tox_friend_get_connection_status(Alice, 0, NULL) == TOX_CONNECTION_UDP &&
315 if (tox_friend_get_connection_status(caller, 0, 0) && 171 tox_friend_get_connection_status(Alice, 1, NULL) == TOX_CONNECTION_UDP &&
316 tox_friend_get_connection_status(caller, 1, 0) && 172 tox_friend_get_connection_status(Alice, 2, NULL) == TOX_CONNECTION_UDP &&
317 tox_friend_get_connection_status(caller, 2, 0) ) 173 tox_friend_get_connection_status(Bobs[0], 0, NULL) == TOX_CONNECTION_UDP &&
174 tox_friend_get_connection_status(Bobs[1], 0, NULL) == TOX_CONNECTION_UDP &&
175 tox_friend_get_connection_status(Bobs[2], 0, NULL) == TOX_CONNECTION_UDP)
318 break; 176 break;
319 177
320 c_sleep(20); 178 c_sleep(20);
321 } 179 }
322 180
323 printf("All set after %llu seconds! Starting call...\n", time(NULL) - cur_time); 181 AliceAV = setup_av_instance(Alice, &AliceCC);
324 182 BobsAV[0] = setup_av_instance(Bobs[0], &BobsCC[0]);
325 ToxAv *uniqcallerav = toxav_new(caller, 3); 183 BobsAV[1] = setup_av_instance(Bobs[1], &BobsCC[1]);
326 184 BobsAV[2] = setup_av_instance(Bobs[2], &BobsCC[2]);
185
186 printf("Created 4 instances of ToxAV\n");
187 printf("All set after %llu seconds!\n", time(NULL) - cur_time);
188
189
190
191 tox_kill(bootstrap);
192 tox_kill(Alice);
193 toxav_kill(AliceAV);
194
327 for (i = 0; i < 3; i ++) { 195 for (i = 0; i < 3; i ++) {
328 status_control.calls[i].idx = i; 196 tox_kill(Bobs[i]);
329 197 toxav_kill(BobsAV[i]);
330 status_control.calls[i].Caller.av = uniqcallerav;
331 status_control.calls[i].Caller.id = 0;
332 status_control.calls[i].Caller.status = none;
333
334 status_control.calls[i].Callee.av = toxav_new(callees[i], 1);
335 status_control.calls[i].Callee.id = i;
336 status_control.calls[i].Callee.status = none;
337 } 198 }
338 199
339 pthread_mutex_init(&muhmutex, NULL); 200 printf("\nTest successful!\n");
340
341 for ( i = 0; i < 3; i++ ) {
342 call_running[i] = 1;
343 pthread_create(&status_control.calls[i].tid, NULL, in_thread_call, &status_control.calls[i]);
344 }
345
346 /* Now start 3 calls and they'll run for 10 s */
347
348 for ( i = 0; i < 3; i++ )
349 pthread_detach(status_control.calls[i].tid);
350
351 while (call_running[0] || call_running[1] || call_running[2]) {
352 pthread_mutex_lock(&muhmutex);
353
354 tox_iterate(bootstrap_node);
355 tox_iterate(caller);
356 tox_iterate(callees[0]);
357 tox_iterate(callees[1]);
358 tox_iterate(callees[2]);
359
360 for ( i = 0; i < 3; i++ )
361 toxav_do(status_control.calls[0].Caller.av);
362
363 toxav_do(status_control.calls[0].Callee.av);
364 toxav_do(status_control.calls[1].Callee.av);
365 toxav_do(status_control.calls[2].Callee.av);
366
367 pthread_mutex_unlock(&muhmutex);
368 c_sleep(20);
369 }
370
371 toxav_kill(status_control.calls[0].Caller.av);
372 toxav_kill(status_control.calls[0].Callee.av);
373 toxav_kill(status_control.calls[1].Callee.av);
374 toxav_kill(status_control.calls[2].Callee.av);
375
376 tox_kill(bootstrap_node);
377 tox_kill(caller);
378
379 for ( i = 0; i < 3; i ++)
380 tox_kill(callees[i]);
381
382} 201}
383END_TEST 202END_TEST
384 203
@@ -410,8 +229,4 @@ int main(int argc, char *argv[])
410 srunner_free(test_runner); 229 srunner_free(test_runner);
411 230
412 return number_failed; 231 return number_failed;
413
414// test_AV_three_calls();
415
416// return 0;
417} 232}
diff --git a/toxav/av_test.c b/testing/av_test.c
index 86deebdf..7298ed23 100644
--- a/toxav/av_test.c
+++ b/testing/av_test.c
@@ -70,13 +70,6 @@
70#define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U) + 128) >> 8) 70#define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U) + 128) >> 8)
71 71
72 72
73/* Enable/disable tests */
74#define TEST_REGULAR_AV 0
75#define TEST_REGULAR_A 0
76#define TEST_REGULAR_V 0
77#define TEST_REJECT 0
78#define TEST_CANCEL 0
79#define TEST_MUTE_UNMUTE 0
80#define TEST_TRANSFER_A 0 73#define TEST_TRANSFER_A 0
81#define TEST_TRANSFER_V 1 74#define TEST_TRANSFER_V 1
82 75
@@ -126,7 +119,7 @@ void* pa_write_thread (void* d)
126} 119}
127 120
128 121
129/** 122/**
130 * Callbacks 123 * Callbacks
131 */ 124 */
132void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data) 125void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data)
@@ -187,21 +180,21 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
187 free(rb_write(cc->arb, f)); 180 free(rb_write(cc->arb, f));
188 pthread_mutex_unlock(cc->arb_mutex); 181 pthread_mutex_unlock(cc->arb_mutex);
189} 182}
190void t_toxav_audio_bitrate_control_cb(ToxAV *av, uint32_t friend_number, 183void t_toxav_audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number,
191 bool good, uint32_t bit_rate, void *user_data) 184 bool stable, uint32_t bit_rate, void *user_data)
192{ 185{
193 if (good) 186 if (stable)
194 printf ("Set new audio bitrate to: %d\n", bit_rate); 187 printf ("Set new audio bit rate to: %d\n", bit_rate);
195 else 188 else
196 printf ("The network is overly saturated with audio bitrate at: %d\n", bit_rate); 189 printf ("The network is overly saturated with audio bit rate at: %d\n", bit_rate);
197} 190}
198void t_toxav_video_bitrate_control_cb(ToxAV *av, uint32_t friend_number, 191void t_toxav_video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number,
199 bool good, uint32_t bit_rate, void *user_data) 192 bool stable, uint32_t bit_rate, void *user_data)
200{ 193{
201 if (good) 194 if (stable)
202 printf ("Set new video bitrate to: %d", bit_rate); 195 printf ("Set new video bit rate to: %d", bit_rate);
203 else 196 else
204 printf ("The network is overly saturated with video bitrate at: %d", bit_rate); 197 printf ("The network is overly saturated with video bit rate at: %d", bit_rate);
205} 198}
206void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) 199void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
207{ 200{
@@ -287,16 +280,16 @@ void initialize_tox(Tox** bootstrap, ToxAV** AliceAV, CallControl* AliceCC, ToxA
287 toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC); 280 toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC);
288 toxav_callback_receive_video_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC); 281 toxav_callback_receive_video_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC);
289 toxav_callback_receive_audio_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC); 282 toxav_callback_receive_audio_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC);
290 toxav_callback_audio_bitrate_control(*AliceAV, t_toxav_audio_bitrate_control_cb, AliceCC); 283 toxav_callback_audio_bit_rate_status(*AliceAV, t_toxav_audio_bit_rate_status_cb, AliceCC);
291 toxav_callback_video_bitrate_control(*AliceAV, t_toxav_video_bitrate_control_cb, AliceCC); 284 toxav_callback_video_bit_rate_status(*AliceAV, t_toxav_video_bit_rate_status_cb, AliceCC);
292 285
293 /* Bob */ 286 /* Bob */
294 toxav_callback_call(*BobAV, t_toxav_call_cb, BobCC); 287 toxav_callback_call(*BobAV, t_toxav_call_cb, BobCC);
295 toxav_callback_call_state(*BobAV, t_toxav_call_state_cb, BobCC); 288 toxav_callback_call_state(*BobAV, t_toxav_call_state_cb, BobCC);
296 toxav_callback_receive_video_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC); 289 toxav_callback_receive_video_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC);
297 toxav_callback_receive_audio_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC); 290 toxav_callback_receive_audio_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC);
298 toxav_callback_audio_bitrate_control(*BobAV, t_toxav_audio_bitrate_control_cb, BobCC); 291 toxav_callback_audio_bit_rate_status(*BobAV, t_toxav_audio_bit_rate_status_cb, BobCC);
299 toxav_callback_video_bitrate_control(*BobAV, t_toxav_video_bitrate_control_cb, BobCC); 292 toxav_callback_video_bit_rate_status(*BobAV, t_toxav_video_bit_rate_status_cb, BobCC);
300 293
301 294
302 printf("Created 2 instances of ToxAV\n"); 295 printf("Created 2 instances of ToxAV\n");
@@ -513,232 +506,7 @@ int main (int argc, char** argv)
513 506
514 initialize_tox(&bootstrap, &AliceAV, &AliceCC, &BobAV, &BobCC); 507 initialize_tox(&bootstrap, &AliceAV, &AliceCC, &BobAV, &BobCC);
515 508
516#define REGULAR_CALL_FLOW(A_BR, V_BR) \ 509 if (TEST_TRANSFER_A) {
517 do { \
518 memset(&AliceCC, 0, sizeof(CallControl)); \
519 memset(&BobCC, 0, sizeof(CallControl)); \
520 \
521 TOXAV_ERR_CALL rc; \
522 toxav_call(AliceAV, 0, A_BR, V_BR, &rc); \
523 \
524 if (rc != TOXAV_ERR_CALL_OK) { \
525 printf("toxav_call failed: %d\n", rc); \
526 exit(1); \
527 } \
528 \
529 \
530 long long unsigned int start_time = time(NULL); \
531 \
532 \
533 while (BobCC.state != TOXAV_CALL_STATE_END) { \
534 \
535 if (BobCC.incoming) { \
536 TOXAV_ERR_ANSWER rc; \
537 toxav_answer(BobAV, 0, A_BR, V_BR, &rc); \
538 \
539 if (rc != TOXAV_ERR_ANSWER_OK) { \
540 printf("toxav_answer failed: %d\n", rc); \
541 exit(1); \
542 } \
543 BobCC.incoming = false; \
544 } else { \
545 /* TODO rtp */ \
546 \
547 if (time(NULL) - start_time == 5) { \
548 \
549 TOXAV_ERR_CALL_CONTROL rc; \
550 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); \
551 \
552 if (rc != TOXAV_ERR_CALL_CONTROL_OK) { \
553 printf("toxav_call_control failed: %d\n", rc); \
554 exit(1); \
555 } \
556 } \
557 } \
558 \
559 iterate_tox(bootstrap, AliceAV, BobAV); \
560 } \
561 printf("Success!\n");\
562 } while(0)
563
564 if (TEST_REGULAR_AV) {
565 printf("\nTrying regular call (Audio and Video)...\n");
566 REGULAR_CALL_FLOW(48, 4000);
567 }
568
569 if (TEST_REGULAR_A) {
570 printf("\nTrying regular call (Audio only)...\n");
571 REGULAR_CALL_FLOW(48, 0);
572 }
573
574 if (TEST_REGULAR_V) {
575 printf("\nTrying regular call (Video only)...\n");
576 REGULAR_CALL_FLOW(0, 4000);
577 }
578
579#undef REGULAR_CALL_FLOW
580
581 if (TEST_REJECT) { /* Alice calls; Bob rejects */
582 printf("\nTrying reject flow...\n");
583
584 memset(&AliceCC, 0, sizeof(CallControl));
585 memset(&BobCC, 0, sizeof(CallControl));
586
587 {
588 TOXAV_ERR_CALL rc;
589 toxav_call(AliceAV, 0, 48, 0, &rc);
590
591 if (rc != TOXAV_ERR_CALL_OK) {
592 printf("toxav_call failed: %d\n", rc);
593 exit(1);
594 }
595 }
596
597 while (!BobCC.incoming)
598 iterate_tox(bootstrap, AliceAV, BobAV);
599
600 /* Reject */
601 {
602 TOXAV_ERR_CALL_CONTROL rc;
603 toxav_call_control(BobAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
604
605 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
606 printf("toxav_call_control failed: %d\n", rc);
607 exit(1);
608 }
609 }
610
611 while (AliceCC.state != TOXAV_CALL_STATE_END)
612 iterate_tox(bootstrap, AliceAV, BobAV);
613
614 printf("Success!\n");
615 }
616
617 if (TEST_CANCEL) { /* Alice calls; Alice cancels while ringing */
618 printf("\nTrying cancel (while ringing) flow...\n");
619
620 memset(&AliceCC, 0, sizeof(CallControl));
621 memset(&BobCC, 0, sizeof(CallControl));
622
623 {
624 TOXAV_ERR_CALL rc;
625 toxav_call(AliceAV, 0, 48, 0, &rc);
626
627 if (rc != TOXAV_ERR_CALL_OK) {
628 printf("toxav_call failed: %d\n", rc);
629 exit(1);
630 }
631 }
632
633 while (!BobCC.incoming)
634 iterate_tox(bootstrap, AliceAV, BobAV);
635
636 /* Cancel */
637 {
638 TOXAV_ERR_CALL_CONTROL rc;
639 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
640
641 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
642 printf("toxav_call_control failed: %d\n", rc);
643 exit(1);
644 }
645 }
646
647 /* Alice will not receive end state */
648 while (BobCC.state != TOXAV_CALL_STATE_END)
649 iterate_tox(bootstrap, AliceAV, BobAV);
650
651 printf("Success!\n");
652 }
653
654 if (TEST_MUTE_UNMUTE) { /* Check Mute-Unmute etc */
655 printf("\nTrying mute functionality...\n");
656
657 memset(&AliceCC, 0, sizeof(CallControl));
658 memset(&BobCC, 0, sizeof(CallControl));
659
660 /* Assume sending audio and video */
661 {
662 TOXAV_ERR_CALL rc;
663 toxav_call(AliceAV, 0, 48, 1000, &rc);
664
665 if (rc != TOXAV_ERR_CALL_OK) {
666 printf("toxav_call failed: %d\n", rc);
667 exit(1);
668 }
669 }
670
671 while (!BobCC.incoming)
672 iterate_tox(bootstrap, AliceAV, BobAV);
673
674 /* At first try all stuff while in invalid state */
675 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
676 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
677 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
678 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL));
679
680 {
681 TOXAV_ERR_ANSWER rc;
682 toxav_answer(BobAV, 0, 48, 4000, &rc);
683
684 if (rc != TOXAV_ERR_ANSWER_OK) {
685 printf("toxav_answer failed: %d\n", rc);
686 exit(1);
687 }
688 }
689
690 iterate_tox(bootstrap, AliceAV, BobAV);
691
692 /* Pause and Resume */
693 printf("Pause and Resume\n");
694 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
695 iterate_tox(bootstrap, AliceAV, BobAV);
696 assert(BobCC.state == TOXAV_CALL_STATE_PAUSED);
697 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
698 iterate_tox(bootstrap, AliceAV, BobAV);
699 assert(BobCC.state & (TOXAV_CALL_STATE_SENDING_A | TOXAV_CALL_STATE_SENDING_V));
700
701 /* Mute/Unmute single */
702 printf("Mute/Unmute single\n");
703 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
704 iterate_tox(bootstrap, AliceAV, BobAV);
705 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
706 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
707 iterate_tox(bootstrap, AliceAV, BobAV);
708 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
709
710 /* Mute/Unmute both */
711 printf("Mute/Unmute both\n");
712 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
713 iterate_tox(bootstrap, AliceAV, BobAV);
714 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
715 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL));
716 iterate_tox(bootstrap, AliceAV, BobAV);
717 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_V);
718 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
719 iterate_tox(bootstrap, AliceAV, BobAV);
720 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
721 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL));
722 iterate_tox(bootstrap, AliceAV, BobAV);
723 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_V);
724
725 {
726 TOXAV_ERR_CALL_CONTROL rc;
727 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
728
729 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
730 printf("toxav_call_control failed: %d\n", rc);
731 exit(1);
732 }
733 }
734
735 iterate_tox(bootstrap, AliceAV, BobAV);
736 assert(BobCC.state == TOXAV_CALL_STATE_END);
737
738 printf("Success!\n");
739 }
740
741 if (TEST_TRANSFER_A) { /* Audio encoding/decoding and transfer */
742 SNDFILE* af_handle; 510 SNDFILE* af_handle;
743 SF_INFO af_info; 511 SF_INFO af_info;
744 512
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc
index 0434a3c6..3907951e 100644
--- a/toxav/Makefile.inc
+++ b/toxav/Makefile.inc
@@ -37,25 +37,4 @@ libtoxav_la_LIBADD = libtoxcore.la \
37 $(PTHREAD_LIBS) \ 37 $(PTHREAD_LIBS) \
38 $(AV_LIBS) 38 $(AV_LIBS)
39 39
40
41
42#noinst_PROGRAMS += av_test
43
44#av_test_SOURCES = ../toxav/av_test.c
45
46#av_test_CFLAGS = $(LIBSODIUM_CFLAGS) \
47 $(NACL_CFLAGS)
48
49#av_test_LDADD = $(LIBSODIUM_LDFLAGS) \
50 $(NACL_LDFLAGS) \
51 libtoxav.la \
52 libtoxcore.la \
53 $(LIBSODIUM_LIBS) \
54 $(NACL_OBJECTS) \
55 -lopenal \
56 -lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_ocl -lopencv_photo -lopencv_stitching -lopencv_superres -lopencv_ts -lopencv_video -lopencv_videostab \
57 -lsndfile \
58 $(NACL_LIBS)
59
60
61endif \ No newline at end of file 40endif \ No newline at end of file
diff --git a/toxav/audio.c b/toxav/audio.c
index 2f068c85..c592a7da 100644
--- a/toxav/audio.c
+++ b/toxav/audio.c
@@ -31,14 +31,14 @@ static void jbuf_clear(struct JitterBuffer *q);
31static void jbuf_free(struct JitterBuffer *q); 31static void jbuf_free(struct JitterBuffer *q);
32static int jbuf_write(struct JitterBuffer *q, RTPMessage *m); 32static int jbuf_write(struct JitterBuffer *q, RTPMessage *m);
33static RTPMessage *jbuf_read(struct JitterBuffer *q, int32_t *success); 33static RTPMessage *jbuf_read(struct JitterBuffer *q, int32_t *success);
34 34OpusEncoder* create_audio_encoder (int32_t bit_rate, int32_t sampling_rate, int32_t channel_count);
35OpusEncoder* create_audio_encoder (int32_t bitrate, int32_t sampling_rate, int32_t channel_count);
36bool reconfigure_audio_encoder(OpusEncoder** e, int32_t new_br, int32_t new_sr, uint8_t new_ch, 35bool reconfigure_audio_encoder(OpusEncoder** e, int32_t new_br, int32_t new_sr, uint8_t new_ch,
37 int32_t *old_br, int32_t *old_sr, int32_t *old_ch); 36 int32_t *old_br, int32_t *old_sr, int32_t *old_ch);
38bool reconfigure_audio_decoder(ACSession* ac, int32_t sampling_rate, int8_t channels); 37bool reconfigure_audio_decoder(ACSession* ac, int32_t sampling_rate, int8_t channels);
39 38
40 39
41ACSession* ac_new(ToxAV* av, uint32_t friend_id, toxav_receive_audio_frame_cb *cb, void *cb_data) 40
41ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data)
42{ 42{
43 ACSession *ac = calloc(sizeof(ACSession), 1); 43 ACSession *ac = calloc(sizeof(ACSession), 1);
44 44
@@ -78,11 +78,11 @@ ACSession* ac_new(ToxAV* av, uint32_t friend_id, toxav_receive_audio_frame_cb *c
78 goto DECODER_CLEANUP; 78 goto DECODER_CLEANUP;
79 } 79 }
80 80
81 ac->last_encoding_bitrate = 48000; 81 ac->last_encoding_bit_rate = 48000;
82 ac->last_encoding_sampling_rate = 48000; 82 ac->last_encoding_sampling_rate = 48000;
83 ac->last_encoding_channel_count = 2; 83 ac->last_encoding_channel_count = 2;
84 84
85 ac->last_test_encoding_bitrate = 48000; 85 ac->last_test_encoding_bit_rate = 48000;
86 ac->last_test_encoding_sampling_rate = 48000; 86 ac->last_test_encoding_sampling_rate = 48000;
87 ac->last_test_encoding_channel_count = 2; 87 ac->last_test_encoding_channel_count = 2;
88 88
@@ -97,7 +97,7 @@ ACSession* ac_new(ToxAV* av, uint32_t friend_id, toxav_receive_audio_frame_cb *c
97 ac->last_packet_channel_count = 1; 97 ac->last_packet_channel_count = 1;
98 98
99 ac->av = av; 99 ac->av = av;
100 ac->friend_id = friend_id; 100 ac->friend_number = friend_number;
101 ac->acb.first = cb; 101 ac->acb.first = cb;
102 ac->acb.second = cb_data; 102 ac->acb.second = cb_data;
103 103
@@ -181,7 +181,7 @@ void ac_do(ACSession* ac)
181 } else if (ac->acb.first) { 181 } else if (ac->acb.first) {
182 ac->last_packet_frame_duration = (rc * 1000) / ac->last_packet_sampling_rate; 182 ac->last_packet_frame_duration = (rc * 1000) / ac->last_packet_sampling_rate;
183 183
184 ac->acb.first(ac->av, ac->friend_id, tmp, rc * ac->last_packet_channel_count, 184 ac->acb.first(ac->av, ac->friend_number, tmp, rc * ac->last_packet_channel_count,
185 ac->last_packet_channel_count, ac->last_packet_sampling_rate, ac->acb.second); 185 ac->last_packet_channel_count, ac->last_packet_sampling_rate, ac->acb.second);
186 } 186 }
187 187
@@ -220,28 +220,27 @@ int ac_queue_message(void* acp, struct RTPMessage_s *msg)
220 220
221 return 0; 221 return 0;
222} 222}
223int ac_reconfigure_encoder(ACSession* ac, int32_t bitrate, int32_t sampling_rate, uint8_t channels) 223int ac_reconfigure_encoder(ACSession* ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels)
224{ 224{
225 if (!ac || !reconfigure_audio_encoder(&ac->encoder, bitrate, sampling_rate, channels, 225 if (!ac || !reconfigure_audio_encoder(&ac->encoder, bit_rate, sampling_rate, channels,
226 &ac->last_encoding_bitrate, &ac->last_encoding_sampling_rate, &ac->last_encoding_channel_count)) 226 &ac->last_encoding_bit_rate, &ac->last_encoding_sampling_rate, &ac->last_encoding_channel_count))
227 return -1; 227 return -1;
228 228
229 LOGGER_DEBUG ("Reconfigured audio encoder br: %d sr: %d cc:%d", bitrate, sampling_rate, channels); 229 LOGGER_DEBUG ("Reconfigured audio encoder br: %d sr: %d cc:%d", bit_rate, sampling_rate, channels);
230 return 0; 230 return 0;
231} 231}
232int ac_reconfigure_test_encoder(ACSession* ac, int32_t bitrate, int32_t sampling_rate, uint8_t channels) 232int ac_reconfigure_test_encoder(ACSession* ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels)
233{ 233{
234 if (!ac || !reconfigure_audio_encoder(&ac->test_encoder, bitrate, sampling_rate, channels, 234 if (!ac || !reconfigure_audio_encoder(&ac->test_encoder, bit_rate, sampling_rate, channels,
235 &ac->last_encoding_bitrate, &ac->last_encoding_sampling_rate, &ac->last_encoding_channel_count)) 235 &ac->last_encoding_bit_rate, &ac->last_encoding_sampling_rate, &ac->last_encoding_channel_count))
236 return -1; 236 return -1;
237 237
238 LOGGER_DEBUG ("Reconfigured test audio encoder br: %d sr: %d cc:%d", bitrate, sampling_rate, channels); 238 LOGGER_DEBUG ("Reconfigured test audio encoder br: %d sr: %d cc:%d", bit_rate, sampling_rate, channels);
239 return 0; 239 return 0;
240} 240}
241 241
242 242
243 243
244/* JITTER BUFFER WORK */
245struct JitterBuffer { 244struct JitterBuffer {
246 RTPMessage **queue; 245 RTPMessage **queue;
247 uint32_t size; 246 uint32_t size;
@@ -340,7 +339,7 @@ static RTPMessage *jbuf_read(struct JitterBuffer *q, int32_t *success)
340 *success = 0; 339 *success = 0;
341 return NULL; 340 return NULL;
342} 341}
343OpusEncoder* create_audio_encoder (int32_t bitrate, int32_t sampling_rate, int32_t channel_count) 342OpusEncoder* create_audio_encoder (int32_t bit_rate, int32_t sampling_rate, int32_t channel_count)
344{ 343{
345 int status = OPUS_OK; 344 int status = OPUS_OK;
346 OpusEncoder* rc = opus_encoder_create(sampling_rate, channel_count, OPUS_APPLICATION_AUDIO, &status); 345 OpusEncoder* rc = opus_encoder_create(sampling_rate, channel_count, OPUS_APPLICATION_AUDIO, &status);
@@ -350,7 +349,7 @@ OpusEncoder* create_audio_encoder (int32_t bitrate, int32_t sampling_rate, int32
350 return NULL; 349 return NULL;
351 } 350 }
352 351
353 status = opus_encoder_ctl(rc, OPUS_SET_BITRATE(bitrate)); 352 status = opus_encoder_ctl(rc, OPUS_SET_BITRATE(bit_rate));
354 353
355 if ( status != OPUS_OK ) { 354 if ( status != OPUS_OK ) {
356 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(status)); 355 LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(status));
diff --git a/toxav/audio.h b/toxav/audio.h
index a36396f1..c003bac0 100644
--- a/toxav/audio.h
+++ b/toxav/audio.h
@@ -31,18 +31,21 @@
31 31
32struct RTPMessage_s; 32struct RTPMessage_s;
33 33
34/*
35 * Base Audio Codec session type.
36 */
34typedef struct ACSession_s { 37typedef struct ACSession_s {
35 /* encoding */ 38 /* encoding */
36 OpusEncoder *encoder; 39 OpusEncoder *encoder;
37 int32_t last_encoding_sampling_rate; 40 int32_t last_encoding_sampling_rate;
38 int32_t last_encoding_channel_count; 41 int32_t last_encoding_channel_count;
39 int32_t last_encoding_bitrate; 42 int32_t last_encoding_bit_rate;
40 43
41 /* Testing encoder for dynamic bitrate streaming */ 44 /* Testing encoder for dynamic bit rate streaming */
42 OpusEncoder *test_encoder; 45 OpusEncoder *test_encoder;
43 int32_t last_test_encoding_sampling_rate; 46 int32_t last_test_encoding_sampling_rate;
44 int32_t last_test_encoding_channel_count; 47 int32_t last_test_encoding_channel_count;
45 int32_t last_test_encoding_bitrate; 48 int32_t last_test_encoding_bit_rate;
46 49
47 /* decoding */ 50 /* decoding */
48 OpusDecoder *decoder; 51 OpusDecoder *decoder;
@@ -57,14 +60,30 @@ typedef struct ACSession_s {
57 pthread_mutex_t queue_mutex[1]; 60 pthread_mutex_t queue_mutex[1];
58 61
59 ToxAV* av; 62 ToxAV* av;
60 uint32_t friend_id; 63 uint32_t friend_number;
61 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ 64 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */
62} ACSession; 65} ACSession;
63 66
64ACSession* ac_new(ToxAV* av, uint32_t friend_id, toxav_receive_audio_frame_cb *cb, void *cb_data); 67/*
68 * Create new Audio Codec session.
69 */
70ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data);
71/*
72 * Kill the Audio Codec session.
73 */
65void ac_kill(ACSession* ac); 74void ac_kill(ACSession* ac);
75/*
76 * Do periodic work. Work is consisted out of decoding only.
77 */
66void ac_do(ACSession* ac); 78void ac_do(ACSession* ac);
79/*
80 * Queue new rtp message.
81 */
67int ac_queue_message(void *acp, struct RTPMessage_s *msg); 82int ac_queue_message(void *acp, struct RTPMessage_s *msg);
68int ac_reconfigure_encoder(ACSession* ac, int32_t bitrate, int32_t sampling_rate, uint8_t channels); 83/*
69int ac_reconfigure_test_encoder(ACSession* ac, int32_t bitrate, int32_t sampling_rate, uint8_t channels); 84 * Set new values to the encoders.
85 */
86int ac_reconfigure_encoder(ACSession* ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels);
87int ac_reconfigure_test_encoder(ACSession* ac, int32_t bit_rate, int32_t sampling_rate, uint8_t channels);
88
70#endif /* AUDIO_H */ \ No newline at end of file 89#endif /* AUDIO_H */ \ No newline at end of file
diff --git a/toxav/msi.c b/toxav/msi.c
index 0bd04c56..f8bc8451 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -75,37 +75,37 @@ typedef struct {
75 MSIHeaderRequest request; 75 MSIHeaderRequest request;
76 MSIHeaderError error; 76 MSIHeaderError error;
77 MSIHeaderCapabilities capabilities; 77 MSIHeaderCapabilities capabilities;
78 MSIHeaderVFPSZ vfpsz; /* Video frame piece size. NOTE: Value must be in network b-order */ 78 MSIHeaderVFPSZ vfpsz; /* Video frame piece size. NOTE: Value must be in network b-order TODO: get rid of this eventually */
79} MSIMessage; 79} MSIMessage;
80 80
81 81
82void msg_init (MSIMessage *dest, MSIRequest request); 82void msg_init (MSIMessage *dest, MSIRequest request);
83int msg_parse_in ( MSIMessage *dest, const uint8_t *data, uint16_t length ); 83int msg_parse_in ( MSIMessage *dest, const uint8_t *data, uint16_t length );
84uint8_t *msg_parse_header_out ( MSIHeaderID id, uint8_t *dest, const void *value, uint8_t value_len, uint16_t *length ); 84uint8_t *msg_parse_header_out ( MSIHeaderID id, uint8_t *dest, const void *value, uint8_t value_len, uint16_t *length );
85int send_message ( Messenger* m, uint32_t friend_id, const MSIMessage *msg ); 85int send_message ( Messenger* m, uint32_t friend_number, const MSIMessage *msg );
86int send_error ( Messenger* m, uint32_t friend_id, MSIError error ); 86int send_error ( Messenger* m, uint32_t friend_number, MSIError error );
87static int invoke_callback(MSICall* call, MSICallbackID cb); 87static int invoke_callback(MSICall* call, MSICallbackID cb);
88static MSICall *get_call ( MSISession *session, uint32_t friend_id ); 88static MSICall *get_call ( MSISession *session, uint32_t friend_number );
89MSICall *new_call ( MSISession *session, uint32_t friend_id ); 89MSICall *new_call ( MSISession *session, uint32_t friend_number );
90void kill_call ( MSICall *call ); 90void kill_call ( MSICall *call );
91void on_peer_status(Messenger *m, uint32_t friend_id, uint8_t status, void *data); 91void on_peer_status(Messenger *m, uint32_t friend_number, uint8_t status, void *data);
92void handle_push ( MSICall *call, const MSIMessage *msg ); 92void handle_push ( MSICall *call, const MSIMessage *msg );
93void handle_pop ( MSICall *call, const MSIMessage *msg ); 93void handle_pop ( MSICall *call, const MSIMessage *msg );
94void handle_msi_packet ( Messenger *m, uint32_t friend_id, const uint8_t *data, uint16_t length, void *object ); 94void handle_msi_packet ( Messenger *m, uint32_t friend_number, const uint8_t *data, uint16_t length, void *object );
95 95
96 96
97/** 97/**
98 * Public functions 98 * Public functions
99 */ 99 */
100void msi_register_callback ( MSISession *session, MSICallbackType callback, MSICallbackID id) 100void msi_register_callback ( MSISession* session, msi_action_cb* callback, MSICallbackID id)
101{ 101{
102 pthread_mutex_lock(session->mutex); 102 pthread_mutex_lock(session->mutex);
103 session->callbacks[id] = callback; 103 session->callbacks[id] = callback;
104 pthread_mutex_unlock(session->mutex); 104 pthread_mutex_unlock(session->mutex);
105} 105}
106MSISession *msi_new ( Messenger *messenger ) 106MSISession *msi_new ( Messenger *m )
107{ 107{
108 if (messenger == NULL) { 108 if (m == NULL) {
109 LOGGER_ERROR("Could not init session on empty messenger!"); 109 LOGGER_ERROR("Could not init session on empty messenger!");
110 return NULL; 110 return NULL;
111 } 111 }
@@ -123,12 +123,12 @@ MSISession *msi_new ( Messenger *messenger )
123 return NULL; 123 return NULL;
124 } 124 }
125 125
126 retu->messenger = messenger; 126 retu->messenger = m;
127 127
128 m_callback_msi_packet(messenger, handle_msi_packet, retu ); 128 m_callback_msi_packet(m, handle_msi_packet, retu );
129 129
130 /* This is called when remote terminates session */ 130 /* This is called when remote terminates session */
131 m_callback_connectionstatus_internal_av(messenger, on_peer_status, retu); 131 m_callback_connectionstatus_internal_av(m, on_peer_status, retu);
132 132
133 LOGGER_DEBUG("New msi session: %p ", retu); 133 LOGGER_DEBUG("New msi session: %p ", retu);
134 return retu; 134 return retu;
@@ -149,7 +149,7 @@ int msi_kill ( MSISession *session )
149 149
150 MSICall* it = get_call(session, session->calls_head); 150 MSICall* it = get_call(session, session->calls_head);
151 for (; it; it = it->next) { 151 for (; it; it = it->next) {
152 send_message(session->messenger, it->friend_id, &msg); 152 send_message(session->messenger, it->friend_number, &msg);
153 kill_call(it); /* This will eventually free session->calls */ 153 kill_call(it); /* This will eventually free session->calls */
154 } 154 }
155 } 155 }
@@ -161,18 +161,18 @@ int msi_kill ( MSISession *session )
161 free ( session ); 161 free ( session );
162 return 0; 162 return 0;
163} 163}
164int msi_invite ( MSISession *session, MSICall **call, uint32_t friend_id, uint8_t capabilities ) 164int msi_invite ( MSISession *session, MSICall **call, uint32_t friend_number, uint8_t capabilities )
165{ 165{
166 LOGGER_DEBUG("Session: %p Inviting friend: %u", session, friend_id); 166 LOGGER_DEBUG("Session: %p Inviting friend: %u", session, friend_number);
167 167
168 pthread_mutex_lock(session->mutex); 168 pthread_mutex_lock(session->mutex);
169 if (get_call(session, friend_id) != NULL) { 169 if (get_call(session, friend_number) != NULL) {
170 LOGGER_ERROR("Already in a call"); 170 LOGGER_ERROR("Already in a call");
171 pthread_mutex_unlock(session->mutex); 171 pthread_mutex_unlock(session->mutex);
172 return -1; 172 return -1;
173 } 173 }
174 174
175 (*call) = new_call ( session, friend_id ); 175 (*call) = new_call ( session, friend_number );
176 176
177 if ( *call == NULL ) { 177 if ( *call == NULL ) {
178 pthread_mutex_unlock(session->mutex); 178 pthread_mutex_unlock(session->mutex);
@@ -190,7 +190,7 @@ int msi_invite ( MSISession *session, MSICall **call, uint32_t friend_id, uint8_
190 msg.vfpsz.exists = true; 190 msg.vfpsz.exists = true;
191 msg.vfpsz.value = VIDEOFRAME_PIECE_SIZE; 191 msg.vfpsz.value = VIDEOFRAME_PIECE_SIZE;
192 192
193 send_message ( (*call)->session->messenger, (*call)->friend_id, &msg ); 193 send_message ( (*call)->session->messenger, (*call)->friend_number, &msg );
194 194
195 (*call)->state = msi_CallRequesting; 195 (*call)->state = msi_CallRequesting;
196 196
@@ -200,7 +200,7 @@ int msi_invite ( MSISession *session, MSICall **call, uint32_t friend_id, uint8_
200} 200}
201int msi_hangup ( MSICall* call ) 201int msi_hangup ( MSICall* call )
202{ 202{
203 LOGGER_DEBUG("Session: %p Hanging up call with friend: %u", call->session, call->friend_id); 203 LOGGER_DEBUG("Session: %p Hanging up call with friend: %u", call->session, call->friend_number);
204 204
205 MSISession* session = call->session; 205 MSISession* session = call->session;
206 pthread_mutex_lock(session->mutex); 206 pthread_mutex_lock(session->mutex);
@@ -208,7 +208,7 @@ int msi_hangup ( MSICall* call )
208 MSIMessage msg; 208 MSIMessage msg;
209 msg_init(&msg, requ_pop); 209 msg_init(&msg, requ_pop);
210 210
211 send_message ( session->messenger, call->friend_id, &msg ); 211 send_message ( session->messenger, call->friend_number, &msg );
212 212
213 kill_call(call); 213 kill_call(call);
214 pthread_mutex_unlock(session->mutex); 214 pthread_mutex_unlock(session->mutex);
@@ -216,7 +216,7 @@ int msi_hangup ( MSICall* call )
216} 216}
217int msi_answer ( MSICall* call, uint8_t capabilities ) 217int msi_answer ( MSICall* call, uint8_t capabilities )
218{ 218{
219 LOGGER_DEBUG("Session: %p Answering call from: %u", call->session, call->friend_id); 219 LOGGER_DEBUG("Session: %p Answering call from: %u", call->session, call->friend_number);
220 220
221 MSISession* session = call->session; 221 MSISession* session = call->session;
222 pthread_mutex_lock(session->mutex); 222 pthread_mutex_lock(session->mutex);
@@ -240,7 +240,7 @@ int msi_answer ( MSICall* call, uint8_t capabilities )
240 msg.vfpsz.exists = true; 240 msg.vfpsz.exists = true;
241 msg.vfpsz.value = VIDEOFRAME_PIECE_SIZE; 241 msg.vfpsz.value = VIDEOFRAME_PIECE_SIZE;
242 242
243 send_message ( session->messenger, call->friend_id, &msg ); 243 send_message ( session->messenger, call->friend_number, &msg );
244 244
245 call->state = msi_CallActive; 245 call->state = msi_CallActive;
246 pthread_mutex_unlock(session->mutex); 246 pthread_mutex_unlock(session->mutex);
@@ -249,7 +249,7 @@ int msi_answer ( MSICall* call, uint8_t capabilities )
249} 249}
250int msi_change_capabilities( MSICall* call, uint8_t capabilities ) 250int msi_change_capabilities( MSICall* call, uint8_t capabilities )
251{ 251{
252 LOGGER_DEBUG("Session: %p Trying to change capabilities to friend %u", call->session, call->friend_id); 252 LOGGER_DEBUG("Session: %p Trying to change capabilities to friend %u", call->session, call->friend_number);
253 253
254 MSISession* session = call->session; 254 MSISession* session = call->session;
255 pthread_mutex_lock(session->mutex); 255 pthread_mutex_lock(session->mutex);
@@ -275,7 +275,7 @@ int msi_change_capabilities( MSICall* call, uint8_t capabilities )
275 msg.capabilities.exists = true; 275 msg.capabilities.exists = true;
276 msg.capabilities.value = capabilities; 276 msg.capabilities.value = capabilities;
277 277
278 send_message ( call->session->messenger, call->friend_id, &msg ); 278 send_message ( call->session->messenger, call->friend_number, &msg );
279 279
280 pthread_mutex_unlock(session->mutex); 280 pthread_mutex_unlock(session->mutex);
281 return 0; 281 return 0;
@@ -394,7 +394,7 @@ uint8_t *msg_parse_header_out ( MSIHeaderID id, uint8_t *dest, const void *value
394 394
395 return dest + value_len; /* Set to next position ready to be written */ 395 return dest + value_len; /* Set to next position ready to be written */
396} 396}
397int send_message ( Messenger* m, uint32_t friend_id, const MSIMessage *msg ) 397int send_message ( Messenger* m, uint32_t friend_number, const MSIMessage *msg )
398{ 398{
399 /* Parse and send message */ 399 /* Parse and send message */
400 assert(m); 400 assert(m);
@@ -438,19 +438,19 @@ int send_message ( Messenger* m, uint32_t friend_id, const MSIMessage *msg )
438 *it = 0; 438 *it = 0;
439 size ++; 439 size ++;
440 440
441 if ( m_msi_packet(m, friend_id, parsed, size) ) { 441 if ( m_msi_packet(m, friend_number, parsed, size) ) {
442 LOGGER_DEBUG("Sent message"); 442 LOGGER_DEBUG("Sent message");
443 return 0; 443 return 0;
444 } 444 }
445 445
446 return -1; 446 return -1;
447} 447}
448int send_error ( Messenger* m, uint32_t friend_id, MSIError error ) 448int send_error ( Messenger* m, uint32_t friend_number, MSIError error )
449{ 449{
450 /* Send error message */ 450 /* Send error message */
451 assert(m); 451 assert(m);
452 452
453 LOGGER_DEBUG("Sending error: %d to friend: %d", error, friend_id); 453 LOGGER_DEBUG("Sending error: %d to friend: %d", error, friend_number);
454 454
455 MSIMessage msg; 455 MSIMessage msg;
456 msg_init(&msg, requ_pop); 456 msg_init(&msg, requ_pop);
@@ -458,7 +458,7 @@ int send_error ( Messenger* m, uint32_t friend_id, MSIError error )
458 msg.error.exists = true; 458 msg.error.exists = true;
459 msg.error.value = error; 459 msg.error.value = error;
460 460
461 send_message ( m, friend_id, &msg ); 461 send_message ( m, friend_number, &msg );
462 return 0; 462 return 0;
463} 463}
464int invoke_callback(MSICall* call, MSICallbackID cb) 464int invoke_callback(MSICall* call, MSICallbackID cb)
@@ -484,16 +484,16 @@ FAILURE:
484 call->error = msi_EHandle; 484 call->error = msi_EHandle;
485 return -1; 485 return -1;
486} 486}
487static MSICall *get_call ( MSISession *session, uint32_t friend_id ) 487static MSICall *get_call ( MSISession *session, uint32_t friend_number )
488{ 488{
489 assert(session); 489 assert(session);
490 490
491 if (session->calls == NULL || session->calls_tail < friend_id) 491 if (session->calls == NULL || session->calls_tail < friend_number)
492 return NULL; 492 return NULL;
493 493
494 return session->calls[friend_id]; 494 return session->calls[friend_number];
495} 495}
496MSICall *new_call ( MSISession *session, uint32_t friend_id ) 496MSICall *new_call ( MSISession *session, uint32_t friend_number )
497{ 497{
498 assert(session); 498 assert(session);
499 499
@@ -503,20 +503,20 @@ MSICall *new_call ( MSISession *session, uint32_t friend_id )
503 return NULL; 503 return NULL;
504 504
505 rc->session = session; 505 rc->session = session;
506 rc->friend_id = friend_id; 506 rc->friend_number = friend_number;
507 507
508 if (session->calls == NULL) { /* Creating */ 508 if (session->calls == NULL) { /* Creating */
509 session->calls = calloc (sizeof(MSICall*), friend_id + 1); 509 session->calls = calloc (sizeof(MSICall*), friend_number + 1);
510 510
511 if (session->calls == NULL) { 511 if (session->calls == NULL) {
512 free(rc); 512 free(rc);
513 return NULL; 513 return NULL;
514 } 514 }
515 515
516 session->calls_tail = session->calls_head = friend_id; 516 session->calls_tail = session->calls_head = friend_number;
517 517
518 } else if (session->calls_tail < friend_id) { /* Appending */ 518 } else if (session->calls_tail < friend_number) { /* Appending */
519 void* tmp = realloc(session->calls, sizeof(MSICall*) * friend_id + 1); 519 void* tmp = realloc(session->calls, sizeof(MSICall*) * friend_number + 1);
520 520
521 if (tmp == NULL) { 521 if (tmp == NULL) {
522 free(rc); 522 free(rc);
@@ -526,22 +526,22 @@ MSICall *new_call ( MSISession *session, uint32_t friend_id )
526 session->calls = tmp; 526 session->calls = tmp;
527 527
528 /* Set fields in between to null */ 528 /* Set fields in between to null */
529 int32_t i = session->calls_tail; 529 int32_t i = session->calls_tail + 1;
530 for (; i < friend_id; i ++) 530 for (; i < friend_number; i ++)
531 session->calls[i] = NULL; 531 session->calls[i] = NULL;
532 532
533 rc->prev = session->calls[session->calls_tail]; 533 rc->prev = session->calls[session->calls_tail];
534 session->calls[session->calls_tail]->next = rc; 534 session->calls[session->calls_tail]->next = rc;
535 535
536 session->calls_tail = friend_id; 536 session->calls_tail = friend_number;
537 537
538 } else if (session->calls_head > friend_id) { /* Inserting at front */ 538 } else if (session->calls_head > friend_number) { /* Inserting at front */
539 rc->next = session->calls[session->calls_head]; 539 rc->next = session->calls[session->calls_head];
540 session->calls[session->calls_head]->prev = rc; 540 session->calls[session->calls_head]->prev = rc;
541 session->calls_head = friend_id; 541 session->calls_head = friend_number;
542 } 542 }
543 543
544 session->calls[friend_id] = rc; 544 session->calls[friend_number] = rc;
545 return rc; 545 return rc;
546} 546}
547void kill_call ( MSICall *call ) 547void kill_call ( MSICall *call )
@@ -560,16 +560,16 @@ void kill_call ( MSICall *call )
560 if (prev) 560 if (prev)
561 prev->next = next; 561 prev->next = next;
562 else if (next) 562 else if (next)
563 session->calls_head = next->friend_id; 563 session->calls_head = next->friend_number;
564 else goto CLEAR_CONTAINER; 564 else goto CLEAR_CONTAINER;
565 565
566 if (next) 566 if (next)
567 next->prev = prev; 567 next->prev = prev;
568 else if (prev) 568 else if (prev)
569 session->calls_tail = prev->friend_id; 569 session->calls_tail = prev->friend_number;
570 else goto CLEAR_CONTAINER; 570 else goto CLEAR_CONTAINER;
571 571
572 session->calls[call->friend_id] = NULL; 572 session->calls[call->friend_number] = NULL;
573 free(call); 573 free(call);
574 return; 574 return;
575 575
@@ -579,17 +579,17 @@ CLEAR_CONTAINER:
579 free(call); 579 free(call);
580 session->calls = NULL; 580 session->calls = NULL;
581} 581}
582void on_peer_status(Messenger* m, uint32_t friend_id, uint8_t status, void* data) 582void on_peer_status(Messenger* m, uint32_t friend_number, uint8_t status, void* data)
583{ 583{
584 (void)m; 584 (void)m;
585 MSISession *session = data; 585 MSISession *session = data;
586 586
587 switch ( status ) { 587 switch ( status ) {
588 case 0: { /* Friend is now offline */ 588 case 0: { /* Friend is now offline */
589 LOGGER_DEBUG("Friend %d is now offline", friend_id); 589 LOGGER_DEBUG("Friend %d is now offline", friend_number);
590 590
591 pthread_mutex_lock(session->mutex); 591 pthread_mutex_lock(session->mutex);
592 MSICall* call = get_call(session, friend_id); 592 MSICall* call = get_call(session, friend_number);
593 593
594 if (call == NULL) { 594 if (call == NULL) {
595 pthread_mutex_unlock(session->mutex); 595 pthread_mutex_unlock(session->mutex);
@@ -610,9 +610,7 @@ void handle_push ( MSICall *call, const MSIMessage *msg )
610{ 610{
611 assert(call); 611 assert(call);
612 612
613 MSISession* session = call->session; 613 LOGGER_DEBUG("Session: %p Handling 'push' friend: %d", call->session, call->friend_number);
614
615 LOGGER_DEBUG("Session: %p Handling 'push' friend: %d", call->session, call->friend_id);
616 614
617 if (!msg->capabilities.exists) { 615 if (!msg->capabilities.exists) {
618 LOGGER_WARNING("Session: %p Invalid capabilities on 'push'"); 616 LOGGER_WARNING("Session: %p Invalid capabilities on 'push'");
@@ -670,7 +668,7 @@ void handle_push ( MSICall *call, const MSIMessage *msg )
670 msg.vfpsz.exists = true; 668 msg.vfpsz.exists = true;
671 msg.vfpsz.value = VIDEOFRAME_PIECE_SIZE; 669 msg.vfpsz.value = VIDEOFRAME_PIECE_SIZE;
672 670
673 send_message ( call->session->messenger, call->friend_id, &msg ); 671 send_message ( call->session->messenger, call->friend_number, &msg );
674 672
675 /* If peer changed capabilities during re-call they will 673 /* If peer changed capabilities during re-call they will
676 * be handled accordingly during the next step 674 * be handled accordingly during the next step
@@ -708,14 +706,14 @@ void handle_push ( MSICall *call, const MSIMessage *msg )
708 return; 706 return;
709 707
710FAILURE: 708FAILURE:
711 send_error(call->session->messenger, call->friend_id, call->error); 709 send_error(call->session->messenger, call->friend_number, call->error);
712 kill_call(call); 710 kill_call(call);
713} 711}
714void handle_pop ( MSICall *call, const MSIMessage *msg ) 712void handle_pop ( MSICall *call, const MSIMessage *msg )
715{ 713{
716 assert(call); 714 assert(call);
717 715
718 LOGGER_DEBUG("Session: %p Handling 'pop', friend id: %d", call->session, call->friend_id); 716 LOGGER_DEBUG("Session: %p Handling 'pop', friend id: %d", call->session, call->friend_number);
719 717
720 /* callback errors are ignored */ 718 /* callback errors are ignored */
721 719
@@ -751,7 +749,7 @@ void handle_pop ( MSICall *call, const MSIMessage *msg )
751 749
752 kill_call ( call ); 750 kill_call ( call );
753} 751}
754void handle_msi_packet ( Messenger* m, uint32_t friend_id, const uint8_t* data, uint16_t length, void* object ) 752void handle_msi_packet ( Messenger* m, uint32_t friend_number, const uint8_t* data, uint16_t length, void* object )
755{ 753{
756 LOGGER_DEBUG("Got msi message"); 754 LOGGER_DEBUG("Got msi message");
757 755
@@ -760,25 +758,25 @@ void handle_msi_packet ( Messenger* m, uint32_t friend_id, const uint8_t* data,
760 758
761 if ( msg_parse_in ( &msg, data, length ) == -1 ) { 759 if ( msg_parse_in ( &msg, data, length ) == -1 ) {
762 LOGGER_WARNING("Error parsing message"); 760 LOGGER_WARNING("Error parsing message");
763 send_error(m, friend_id, msi_EInvalidMessage); 761 send_error(m, friend_number, msi_EInvalidMessage);
764 return; 762 return;
765 } else { 763 } else {
766 LOGGER_DEBUG("Successfully parsed message"); 764 LOGGER_DEBUG("Successfully parsed message");
767 } 765 }
768 766
769 pthread_mutex_lock(session->mutex); 767 pthread_mutex_lock(session->mutex);
770 MSICall *call = get_call(session, friend_id); 768 MSICall *call = get_call(session, friend_number);
771 769
772 if (call == NULL) { 770 if (call == NULL) {
773 if (msg.request.value != requ_push) { 771 if (msg.request.value != requ_push) {
774 send_error(m, friend_id, msi_EStrayMessage); 772 send_error(m, friend_number, msi_EStrayMessage);
775 pthread_mutex_unlock(session->mutex); 773 pthread_mutex_unlock(session->mutex);
776 return; 774 return;
777 } 775 }
778 776
779 call = new_call(session, friend_id); 777 call = new_call(session, friend_number);
780 if (call == NULL) { 778 if (call == NULL) {
781 send_error(m, friend_id, msi_ESystem); 779 send_error(m, friend_number, msi_ESystem);
782 pthread_mutex_unlock(session->mutex); 780 pthread_mutex_unlock(session->mutex);
783 return; 781 return;
784 } 782 }
diff --git a/toxav/msi.h b/toxav/msi.h
index 457d3148..4836ae89 100644
--- a/toxav/msi.h
+++ b/toxav/msi.h
@@ -89,7 +89,7 @@ typedef struct MSICall_s {
89 uint8_t peer_capabilities; /* Peer capabilities */ 89 uint8_t peer_capabilities; /* Peer capabilities */
90 uint8_t self_capabilities; /* Self capabilities */ 90 uint8_t self_capabilities; /* Self capabilities */
91 uint16_t peer_vfpsz; /* Video frame piece size */ 91 uint16_t peer_vfpsz; /* Video frame piece size */
92 uint32_t friend_id; /* Index of this call in MSISession */ 92 uint32_t friend_number; /* Index of this call in MSISession */
93 MSIError error; /* Last error */ 93 MSIError error; /* Last error */
94 94
95 void* av_call; /* Pointer to av call handler */ 95 void* av_call; /* Pointer to av call handler */
@@ -100,12 +100,11 @@ typedef struct MSICall_s {
100 100
101 101
102/** 102/**
103 * Msi callback type. 'agent' is a pointer to ToxAv.
104 * Expected return on success is 0, if any other number is 103 * Expected return on success is 0, if any other number is
105 * returned the call is considered errored and will be handled 104 * returned the call is considered errored and will be handled
106 * as such which means it will be terminated without any notice. 105 * as such which means it will be terminated without any notice.
107 */ 106 */
108typedef int ( *MSICallbackType ) ( void *agent, MSICall* call); 107typedef int msi_action_cb ( void *av, MSICall* call);
109 108
110/** 109/**
111 * Control session struct. Please do not modify outside msi.c 110 * Control session struct. Please do not modify outside msi.c
@@ -119,43 +118,34 @@ typedef struct MSISession_s {
119 void *av; 118 void *av;
120 Messenger *messenger; 119 Messenger *messenger;
121 120
122 /* The mutex controls async access from control
123 * thread(s) and core thread.
124 */
125 pthread_mutex_t mutex[1]; 121 pthread_mutex_t mutex[1];
126 MSICallbackType callbacks[7]; 122 msi_action_cb* callbacks[7];
127} MSISession; 123} MSISession;
128 124
129/** 125/**
130 * Start the control session. 126 * Start the control session.
131 */ 127 */
132MSISession *msi_new ( Messenger *messenger ); 128MSISession *msi_new ( Messenger *m );
133
134/** 129/**
135 * Terminate control session. NOTE: all calls will be freed 130 * Terminate control session. NOTE: all calls will be freed
136 */ 131 */
137int msi_kill ( MSISession *session ); 132int msi_kill ( MSISession *session );
138
139/** 133/**
140 * Callback setter. 134 * Callback setter.
141 */ 135 */
142void msi_register_callback(MSISession *session, MSICallbackType callback, MSICallbackID id); 136void msi_register_callback(MSISession *session, msi_action_cb* callback, MSICallbackID id);
143
144/** 137/**
145 * Send invite request to friend_id. 138 * Send invite request to friend_number.
146 */ 139 */
147int msi_invite ( MSISession* session, MSICall** call, uint32_t friend_id, uint8_t capabilities ); 140int msi_invite ( MSISession* session, MSICall** call, uint32_t friend_number, uint8_t capabilities );
148
149/** 141/**
150 * Hangup call. NOTE: 'call' will be freed 142 * Hangup call. NOTE: 'call' will be freed
151 */ 143 */
152int msi_hangup ( MSICall* call ); 144int msi_hangup ( MSICall* call );
153
154/** 145/**
155 * Answer call request. 146 * Answer call request.
156 */ 147 */
157int msi_answer ( MSICall* call, uint8_t capabilities ); 148int msi_answer ( MSICall* call, uint8_t capabilities );
158
159/** 149/**
160 * Change capabilities of the call. 150 * Change capabilities of the call.
161 */ 151 */
diff --git a/toxav/rtp.c b/toxav/rtp.c
index 6c603f79..2219805b 100644
--- a/toxav/rtp.c
+++ b/toxav/rtp.c
@@ -78,11 +78,11 @@ int handle_rtcp_packet ( Messenger *m, uint32_t friendnumber, const uint8_t *dat
78void send_rtcp_report ( RTCPSession* session, Messenger* m, uint32_t friendnumber ); 78void send_rtcp_report ( RTCPSession* session, Messenger* m, uint32_t friendnumber );
79 79
80 80
81RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num, void* cs, int (*mcb) (void*, RTPMessage*) ) 81RTPSession *rtp_new ( int payload_type, Messenger *m, int friend_num, void* cs, int (*mcb) (void*, RTPMessage*) )
82{ 82{
83 assert(mcb); 83 assert(mcb);
84 assert(cs); 84 assert(cs);
85 assert(messenger); 85 assert(m);
86 86
87 RTPSession *retu = calloc(1, sizeof(RTPSession)); 87 RTPSession *retu = calloc(1, sizeof(RTPSession));
88 88
@@ -95,8 +95,8 @@ RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num, vo
95 retu->ssrc = random_int(); 95 retu->ssrc = random_int();
96 retu->payload_type = payload_type % 128; 96 retu->payload_type = payload_type % 128;
97 97
98 retu->m = messenger; 98 retu->m = m;
99 retu->friend_id = friend_num; 99 retu->friend_number = friend_num;
100 100
101 if ( !(retu->csrc = calloc(1, sizeof(uint32_t))) ) { 101 if ( !(retu->csrc = calloc(1, sizeof(uint32_t))) ) {
102 LOGGER_WARNING("Alloc failed! Program might misbehave!"); 102 LOGGER_WARNING("Alloc failed! Program might misbehave!");
@@ -161,7 +161,7 @@ int rtp_do(RTPSession *session)
161 return rtp_StateNormal; 161 return rtp_StateNormal;
162 162
163 if (current_time_monotonic() - session->rtcp_session->last_sent_report_ts >= RTCP_REPORT_INTERVAL_MS) { 163 if (current_time_monotonic() - session->rtcp_session->last_sent_report_ts >= RTCP_REPORT_INTERVAL_MS) {
164 send_rtcp_report(session->rtcp_session, session->m, session->friend_id); 164 send_rtcp_report(session->rtcp_session, session->m, session->friend_number);
165 } 165 }
166 166
167 if (rb_full(session->rtcp_session->pl_stats)) { 167 if (rb_full(session->rtcp_session->pl_stats)) {
@@ -209,15 +209,15 @@ int rtp_start_receiving(RTPSession* session)
209 if (session == NULL) 209 if (session == NULL)
210 return -1; 210 return -1;
211 211
212 if (m_callback_rtp_packet(session->m, session->friend_id, session->prefix, 212 if (m_callback_rtp_packet(session->m, session->friend_number, session->prefix,
213 handle_rtp_packet, session) == -1) { 213 handle_rtp_packet, session) == -1) {
214 LOGGER_WARNING("Failed to register rtp receive handler"); 214 LOGGER_WARNING("Failed to register rtp receive handler");
215 return -1; 215 return -1;
216 } 216 }
217 if (m_callback_rtp_packet(session->m, session->friend_id, session->rtcp_session->prefix, 217 if (m_callback_rtp_packet(session->m, session->friend_number, session->rtcp_session->prefix,
218 handle_rtcp_packet, session->rtcp_session) == -1) { 218 handle_rtcp_packet, session->rtcp_session) == -1) {
219 LOGGER_WARNING("Failed to register rtcp receive handler"); 219 LOGGER_WARNING("Failed to register rtcp receive handler");
220 m_callback_rtp_packet(session->m, session->friend_id, session->prefix, NULL, NULL); 220 m_callback_rtp_packet(session->m, session->friend_number, session->prefix, NULL, NULL);
221 return -1; 221 return -1;
222 } 222 }
223 223
@@ -228,8 +228,8 @@ int rtp_stop_receiving(RTPSession* session)
228 if (session == NULL) 228 if (session == NULL)
229 return -1; 229 return -1;
230 230
231 m_callback_rtp_packet(session->m, session->friend_id, session->prefix, NULL, NULL); 231 m_callback_rtp_packet(session->m, session->friend_number, session->prefix, NULL, NULL);
232 m_callback_rtp_packet(session->m, session->friend_id, session->rtcp_session->prefix, NULL, NULL); /* RTCP */ 232 m_callback_rtp_packet(session->m, session->friend_number, session->rtcp_session->prefix, NULL, NULL); /* RTCP */
233 233
234 return 0; 234 return 0;
235} 235}
@@ -243,7 +243,8 @@ int rtp_send_data ( RTPSession *session, const uint8_t *data, uint16_t length, b
243 uint8_t parsed[MAX_RTP_SIZE]; 243 uint8_t parsed[MAX_RTP_SIZE];
244 uint8_t *it; 244 uint8_t *it;
245 245
246 RTPHeader header[1]; 246 RTPHeader header[1] = {0};
247
247 ADD_FLAG_VERSION ( header, session->version ); 248 ADD_FLAG_VERSION ( header, session->version );
248 ADD_FLAG_PADDING ( header, session->padding ); 249 ADD_FLAG_PADDING ( header, session->padding );
249 ADD_FLAG_EXTENSION ( header, session->extension ); 250 ADD_FLAG_EXTENSION ( header, session->extension );
@@ -278,12 +279,11 @@ int rtp_send_data ( RTPSession *session, const uint8_t *data, uint16_t length, b
278 279
279 memcpy(it, data, length); 280 memcpy(it, data, length);
280 281
281 if ( -1 == send_custom_lossy_packet(session->m, session->friend_id, parsed, parsed_len) ) { 282 if ( -1 == send_custom_lossy_packet(session->m, session->friend_number, parsed, parsed_len) ) {
282 LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", length, strerror(errno)); 283 LOGGER_WARNING("Failed to send full packet (len: %d)! std error: %s", length, strerror(errno));
283 return -1; 284 return -1;
284 } 285 }
285 286
286 /* Set sequ number */
287 session->sequnum = session->sequnum >= MAX_SEQU_NUM ? 0 : session->sequnum + 1; 287 session->sequnum = session->sequnum >= MAX_SEQU_NUM ? 0 : session->sequnum + 1;
288 return 0; 288 return 0;
289} 289}
@@ -300,7 +300,6 @@ void rtp_free_msg ( RTPMessage *msg )
300 300
301 301
302 302
303
304RTPHeader *parse_header_in ( const uint8_t *payload, int length ) 303RTPHeader *parse_header_in ( const uint8_t *payload, int length )
305{ 304{
306 if ( !payload || !length ) { 305 if ( !payload || !length ) {
@@ -322,12 +321,7 @@ RTPHeader *parse_header_in ( const uint8_t *payload, int length )
322 321
323 retu->flags = *it; 322 retu->flags = *it;
324 ++it; 323 ++it;
325 324
326 /* This indicates if the first 2 bits are valid.
327 * Now it may happen that this is out of order but
328 * it cuts down chances of parsing some invalid value
329 */
330
331 if ( GET_FLAG_VERSION(retu) != RTP_VERSION ) { 325 if ( GET_FLAG_VERSION(retu) != RTP_VERSION ) {
332 /* Deallocate */ 326 /* Deallocate */
333 LOGGER_WARNING("Invalid version!"); 327 LOGGER_WARNING("Invalid version!");
@@ -335,15 +329,10 @@ RTPHeader *parse_header_in ( const uint8_t *payload, int length )
335 return NULL; 329 return NULL;
336 } 330 }
337 331
338 /*
339 * Added a check for the size of the header little sooner so
340 * I don't need to parse the other stuff if it's bad
341 */
342 uint8_t cc = GET_FLAG_CSRCC ( retu ); 332 uint8_t cc = GET_FLAG_CSRCC ( retu );
343 int total = 12 /* Minimum header len */ + ( cc * 4 ); 333 int total = 12 /* Minimum header len */ + ( cc * 4 );
344 334
345 if ( length < total ) { 335 if ( length < total ) {
346 /* Deallocate */
347 LOGGER_WARNING("Length invalid!"); 336 LOGGER_WARNING("Length invalid!");
348 free(retu); 337 free(retu);
349 return NULL; 338 return NULL;
@@ -355,9 +344,10 @@ RTPHeader *parse_header_in ( const uint8_t *payload, int length )
355 344
356 345
357 memcpy(&retu->timestamp, it, sizeof(retu->timestamp)); 346 memcpy(&retu->timestamp, it, sizeof(retu->timestamp));
358 retu->timestamp = ntohl(retu->timestamp);
359 it += 4; 347 it += 4;
360 memcpy(&retu->ssrc, it, sizeof(retu->ssrc)); 348 memcpy(&retu->ssrc, it, sizeof(retu->ssrc));
349
350 retu->timestamp = ntohl(retu->timestamp);
361 retu->ssrc = ntohl(retu->ssrc); 351 retu->ssrc = ntohl(retu->ssrc);
362 352
363 uint8_t x; 353 uint8_t x;
@@ -380,34 +370,31 @@ RTPExtHeader *parse_ext_header_in ( const uint8_t *payload, uint16_t length )
380 return NULL; 370 return NULL;
381 } 371 }
382 372
383 uint16_t ext_length; 373 memcpy(&retu->length, it, sizeof(retu->length));
384 memcpy(&ext_length, it, sizeof(ext_length)); 374 retu->length = ntohs(retu->length);
385 ext_length = ntohs(ext_length);
386 it += 2; 375 it += 2;
387 376
388 377 if ( length < ( retu->length * sizeof(uint32_t) ) ) {
389 if ( length < ( ext_length * sizeof(uint32_t) ) ) {
390 LOGGER_WARNING("Length invalid!"); 378 LOGGER_WARNING("Length invalid!");
391 free(retu); 379 free(retu);
392 return NULL; 380 return NULL;
393 } 381 }
394 382
395 retu->length = ext_length;
396 memcpy(&retu->type, it, sizeof(retu->type)); 383 memcpy(&retu->type, it, sizeof(retu->type));
397 retu->type = ntohs(retu->type); 384 retu->type = ntohs(retu->type);
385
398 it += 2; 386 it += 2;
399 387
400 if ( !(retu->table = calloc(ext_length, sizeof (uint32_t))) ) { 388 if ( !(retu->table = calloc(retu->length, sizeof (uint32_t))) ) {
401 LOGGER_WARNING("Alloc failed! Program might misbehave!"); 389 LOGGER_WARNING("Alloc failed! Program might misbehave!");
402 free(retu); 390 free(retu);
403 return NULL; 391 return NULL;
404 } 392 }
405 393
406 uint16_t x; 394 uint16_t x;
407 395 for ( x = 0; x < retu->length; x++ ) {
408 for ( x = 0; x < ext_length; x++ ) {
409 it += 4; 396 it += 4;
410 memcpy(&(retu->table[x]), it, sizeof(retu->table[x])); 397 memcpy(retu->table + x, it, sizeof(*retu->table));
411 retu->table[x] = ntohl(retu->table[x]); 398 retu->table[x] = ntohl(retu->table[x]);
412 } 399 }
413 400
@@ -433,7 +420,6 @@ uint8_t *parse_header_out ( const RTPHeader *header, uint8_t *payload )
433 *it = header->marker_payloadt; 420 *it = header->marker_payloadt;
434 ++it; 421 ++it;
435 422
436
437 timestamp = htonl(header->timestamp); 423 timestamp = htonl(header->timestamp);
438 memcpy(it, &timestamp, sizeof(timestamp)); 424 memcpy(it, &timestamp, sizeof(timestamp));
439 it += 4; 425 it += 4;
@@ -579,7 +565,6 @@ int handle_rtcp_packet ( Messenger* m, uint32_t friendnumber, const uint8_t* dat
579 report->received_packets = ntohl(report->received_packets); 565 report->received_packets = ntohl(report->received_packets);
580 report->expected_packets = ntohl(report->expected_packets); 566 report->expected_packets = ntohl(report->expected_packets);
581 567
582 /* Invalid values */
583 if (report->expected_packets == 0 || report->received_packets > report->expected_packets) { 568 if (report->expected_packets == 0 || report->received_packets > report->expected_packets) {
584 LOGGER_WARNING("Malformed rtcp report! %d %d", report->expected_packets, report->received_packets); 569 LOGGER_WARNING("Malformed rtcp report! %d %d", report->expected_packets, report->received_packets);
585 free(report); 570 free(report);
diff --git a/toxav/rtp.h b/toxav/rtp.h
index c973d262..a158d724 100644
--- a/toxav/rtp.h
+++ b/toxav/rtp.h
@@ -113,10 +113,9 @@ typedef struct {
113 uint8_t prefix; 113 uint8_t prefix;
114 114
115 Messenger *m; 115 Messenger *m;
116 int friend_id; 116 int friend_number;
117 struct RTCPSession_s *rtcp_session; 117 struct RTCPSession_s *rtcp_session;
118 118
119
120 void *cs; 119 void *cs;
121 int (*mcb) (void*, RTPMessage* msg); 120 int (*mcb) (void*, RTPMessage* msg);
122 121
@@ -125,33 +124,27 @@ typedef struct {
125/** 124/**
126 * Must be called before calling any other rtp function. 125 * Must be called before calling any other rtp function.
127 */ 126 */
128RTPSession *rtp_new ( int payload_type, Messenger *messenger, int friend_num, void* cs, int (*mcb) (void*, RTPMessage*) ); 127RTPSession *rtp_new ( int payload_type, Messenger *m, int friend_num, void* cs, int (*mcb) (void*, RTPMessage*) );
129
130/** 128/**
131 * Terminate the session. 129 * Terminate the session.
132 */ 130 */
133void rtp_kill ( RTPSession* session ); 131void rtp_kill ( RTPSession* session );
134
135/** 132/**
136 * Do periodical rtp work. 133 * Do periodical rtp work.
137 */ 134 */
138int rtp_do(RTPSession *session); 135int rtp_do(RTPSession *session);
139
140/** 136/**
141 * By default rtp is in receiving state 137 * By default rtp is in receiving state
142 */ 138 */
143int rtp_start_receiving (RTPSession *session); 139int rtp_start_receiving (RTPSession *session);
144
145/** 140/**
146 * Pause rtp receiving mode. 141 * Pause rtp receiving mode.
147 */ 142 */
148int rtp_stop_receiving (RTPSession *session); 143int rtp_stop_receiving (RTPSession *session);
149
150/** 144/**
151 * Sends msg to RTPSession::dest 145 * Sends msg to RTPSession::dest
152 */ 146 */
153int rtp_send_data ( RTPSession* session, const uint8_t* data, uint16_t length, bool dummy ); 147int rtp_send_data ( RTPSession* session, const uint8_t* data, uint16_t length, bool dummy );
154
155/** 148/**
156 * Dealloc msg. 149 * Dealloc msg.
157 */ 150 */
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 8d47f5cd..25a2857c 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -58,10 +58,10 @@ typedef struct ToxAVCall_s {
58 58
59 bool active; 59 bool active;
60 MSICall* msi_call; 60 MSICall* msi_call;
61 uint32_t friend_id; 61 uint32_t friend_number;
62 62
63 uint32_t audio_bit_rate; /* Sending audio bitrate */ 63 uint32_t audio_bit_rate; /* Sending audio bit rate */
64 uint32_t video_bit_rate; /* Sending video bitrate */ 64 uint32_t video_bit_rate; /* Sending video bit rate */
65 65
66 ToxAvBitrateAdapter aba; 66 ToxAvBitrateAdapter aba;
67 ToxAvBitrateAdapter vba; 67 ToxAvBitrateAdapter vba;
@@ -93,8 +93,8 @@ struct toxAV {
93 PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */ 93 PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */
94 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ 94 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */
95 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ 95 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */
96 PAIR(toxav_audio_bitrate_control_cb *, void *) abcb; /* Audio bitrate control callback */ 96 PAIR(toxav_audio_bit_rate_status_cb *, void *) abcb; /* Audio bit rate control callback */
97 PAIR(toxav_video_bitrate_control_cb *, void *) vbcb; /* Video bitrate control callback */ 97 PAIR(toxav_video_bit_rate_status_cb *, void *) vbcb; /* Video bit rate control callback */
98 98
99 /** Decode time measures */ 99 /** Decode time measures */
100 int32_t dmssc; /** Measure count */ 100 int32_t dmssc; /** Measure count */
@@ -111,8 +111,8 @@ int callback_end(void* toxav_inst, MSICall* call);
111int callback_error(void* toxav_inst, MSICall* call); 111int callback_error(void* toxav_inst, MSICall* call);
112int callback_capabilites(void* toxav_inst, MSICall* call); 112int callback_capabilites(void* toxav_inst, MSICall* call);
113 113
114bool audio_bitrate_invalid(uint32_t bitrate); 114bool audio_bit_rate_invalid(uint32_t bit_rate);
115bool video_bitrate_invalid(uint32_t bitrate); 115bool video_bit_rate_invalid(uint32_t bit_rate);
116void invoke_call_state(ToxAV* av, uint32_t friend_number, uint32_t state); 116void invoke_call_state(ToxAV* av, uint32_t friend_number, uint32_t state);
117ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error); 117ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error);
118ToxAVCall* call_get(ToxAV* av, uint32_t friend_number); 118ToxAVCall* call_get(ToxAV* av, uint32_t friend_number);
@@ -129,12 +129,12 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
129 129
130 if (tox == NULL) { 130 if (tox == NULL) {
131 rc = TOXAV_ERR_NEW_NULL; 131 rc = TOXAV_ERR_NEW_NULL;
132 goto FAILURE; 132 goto END;
133 } 133 }
134 134
135 if (((Messenger*)tox)->msi_packet) { 135 if (((Messenger*)tox)->msi_packet) {
136 rc = TOXAV_ERR_NEW_MULTIPLE; 136 rc = TOXAV_ERR_NEW_MULTIPLE;
137 goto FAILURE; 137 goto END;
138 } 138 }
139 139
140 av = calloc (sizeof(ToxAV), 1); 140 av = calloc (sizeof(ToxAV), 1);
@@ -142,13 +142,13 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
142 if (av == NULL) { 142 if (av == NULL) {
143 LOGGER_WARNING("Allocation failed!"); 143 LOGGER_WARNING("Allocation failed!");
144 rc = TOXAV_ERR_NEW_MALLOC; 144 rc = TOXAV_ERR_NEW_MALLOC;
145 goto FAILURE; 145 goto END;
146 } 146 }
147 147
148 if (create_recursive_mutex(av->mutex) != 0) { 148 if (create_recursive_mutex(av->mutex) != 0) {
149 LOGGER_WARNING("Mutex creation failed!"); 149 LOGGER_WARNING("Mutex creation failed!");
150 rc = TOXAV_ERR_NEW_MALLOC; 150 rc = TOXAV_ERR_NEW_MALLOC;
151 goto FAILURE; 151 goto END;
152 } 152 }
153 153
154 av->m = (Messenger *)tox; 154 av->m = (Messenger *)tox;
@@ -157,7 +157,7 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
157 if (av->msi == NULL) { 157 if (av->msi == NULL) {
158 pthread_mutex_destroy(av->mutex); 158 pthread_mutex_destroy(av->mutex);
159 rc = TOXAV_ERR_NEW_MALLOC; 159 rc = TOXAV_ERR_NEW_MALLOC;
160 goto FAILURE; 160 goto END;
161 } 161 }
162 162
163 av->interval = 200; 163 av->interval = 200;
@@ -170,19 +170,16 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
170 msi_register_callback(av->msi, callback_error, msi_OnPeerTimeout); 170 msi_register_callback(av->msi, callback_error, msi_OnPeerTimeout);
171 msi_register_callback(av->msi, callback_capabilites, msi_OnCapabilities); 171 msi_register_callback(av->msi, callback_capabilites, msi_OnCapabilities);
172 172
173 173END:
174 if (error)
175 *error = rc;
176
177 return av;
178
179FAILURE:
180 if (error) 174 if (error)
181 *error = rc; 175 *error = rc;
182 176
183 free(av); 177 if (rc != TOXAV_ERR_NEW_OK) {
178 free(av);
179 av = NULL;
180 }
184 181
185 return NULL; 182 return av;
186} 183}
187 184
188void toxav_kill(ToxAV* av) 185void toxav_kill(ToxAV* av)
@@ -249,14 +246,14 @@ void toxav_iterate(ToxAV* av)
249 246
250 /* Notify app */ 247 /* Notify app */
251 if (av->abcb.first) 248 if (av->abcb.first)
252 av->abcb.first (av, i->friend_id, false, bb, av->abcb.second); 249 av->abcb.first (av, i->friend_number, false, bb, av->abcb.second);
253 } else if (i->aba.active && i->aba.end_time < current_time_monotonic()) { 250 } else if (i->aba.active && i->aba.end_time < current_time_monotonic()) {
254 251
255 i->audio_bit_rate = i->aba.bit_rate; 252 i->audio_bit_rate = i->aba.bit_rate;
256 253
257 /* Notify user about the new bitrate */ 254 /* Notify user about the new bit rate */
258 if (av->abcb.first) 255 if (av->abcb.first)
259 av->abcb.first (av, i->friend_id, true, i->aba.bit_rate, av->abcb.second); 256 av->abcb.first (av, i->friend_number, true, i->aba.bit_rate, av->abcb.second);
260 257
261 /* Stop sending dummy packets */ 258 /* Stop sending dummy packets */
262 memset(&i->aba, 0, sizeof(i->aba)); 259 memset(&i->aba, 0, sizeof(i->aba));
@@ -275,15 +272,15 @@ void toxav_iterate(ToxAV* av)
275 272
276 /* Notify app */ 273 /* Notify app */
277 if (av->vbcb.first) 274 if (av->vbcb.first)
278 av->vbcb.first (av, i->friend_id, false, bb, av->vbcb.second); 275 av->vbcb.first (av, i->friend_number, false, bb, av->vbcb.second);
279 276
280 } else if (i->vba.active && i->vba.end_time < current_time_monotonic()) { 277 } else if (i->vba.active && i->vba.end_time < current_time_monotonic()) {
281 278
282 i->video_bit_rate = i->vba.bit_rate; 279 i->video_bit_rate = i->vba.bit_rate;
283 280
284 /* Notify user about the new bitrate */ 281 /* Notify user about the new bit rate */
285 if (av->vbcb.first) 282 if (av->vbcb.first)
286 av->vbcb.first (av, i->friend_id, true, i->vba.bit_rate, av->vbcb.second); 283 av->vbcb.first (av, i->friend_number, true, i->vba.bit_rate, av->vbcb.second);
287 284
288 /* Stop sending dummy packets */ 285 /* Stop sending dummy packets */
289 memset(&i->vba, 0, sizeof(i->vba)); 286 memset(&i->vba, 0, sizeof(i->vba));
@@ -297,7 +294,7 @@ void toxav_iterate(ToxAV* av)
297 i->msi_call->peer_capabilities & msi_CapSVideo) 294 i->msi_call->peer_capabilities & msi_CapSVideo)
298 rc = MIN(i->video.second->lcfd, rc); 295 rc = MIN(i->video.second->lcfd, rc);
299 296
300 uint32_t fid = i->friend_id; 297 uint32_t fid = i->friend_number;
301 298
302 pthread_mutex_unlock(i->mutex); 299 pthread_mutex_unlock(i->mutex);
303 pthread_mutex_lock(av->mutex); 300 pthread_mutex_lock(av->mutex);
@@ -356,7 +353,7 @@ void toxav_callback_call(ToxAV* av, toxav_call_cb* function, void* user_data)
356 av->ccb.first = function; 353 av->ccb.first = function;
357 av->ccb.second = user_data; 354 av->ccb.second = user_data;
358 pthread_mutex_unlock(av->mutex); 355 pthread_mutex_unlock(av->mutex);
359}/** Required for monitoring */ 356}
360 357
361bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER* error) 358bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER* error)
362{ 359{
@@ -368,8 +365,8 @@ bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, ui
368 goto END; 365 goto END;
369 } 366 }
370 367
371 if ((audio_bit_rate && audio_bitrate_invalid(audio_bit_rate)) 368 if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate))
372 ||(video_bit_rate && video_bitrate_invalid(video_bit_rate)) 369 ||(video_bit_rate && video_bit_rate_invalid(video_bit_rate))
373 ) { 370 ) {
374 rc = TOXAV_ERR_CALL_INVALID_BIT_RATE; 371 rc = TOXAV_ERR_CALL_INVALID_BIT_RATE;
375 goto END; 372 goto END;
@@ -561,7 +558,7 @@ END:
561 return rc == TOXAV_ERR_CALL_CONTROL_OK; 558 return rc == TOXAV_ERR_CALL_CONTROL_OK;
562} 559}
563 560
564void toxav_callback_video_bitrate_control(ToxAV* av, toxav_video_bitrate_control_cb* function, void* user_data) 561void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data)
565{ 562{
566 pthread_mutex_lock(av->mutex); 563 pthread_mutex_lock(av->mutex);
567 av->vbcb.first = function; 564 av->vbcb.first = function;
@@ -579,7 +576,7 @@ bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_
579 goto END; 576 goto END;
580 } 577 }
581 578
582 if (video_bitrate_invalid(video_bit_rate)) { 579 if (video_bit_rate_invalid(video_bit_rate)) {
583 rc = TOXAV_ERR_BIT_RATE_INVALID; 580 rc = TOXAV_ERR_BIT_RATE_INVALID;
584 goto END; 581 goto END;
585 } 582 }
@@ -605,7 +602,7 @@ bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_
605 call->video_bit_rate = video_bit_rate; 602 call->video_bit_rate = video_bit_rate;
606 603
607 if (!force && av->vbcb.first) 604 if (!force && av->vbcb.first)
608 av->vbcb.first (av, call->friend_id, true, video_bit_rate, av->vbcb.second); 605 av->vbcb.first (av, call->friend_number, true, video_bit_rate, av->vbcb.second);
609 } 606 }
610 607
611 pthread_mutex_unlock(call->mutex); 608 pthread_mutex_unlock(call->mutex);
@@ -618,7 +615,7 @@ END:
618 return rc == TOXAV_ERR_BIT_RATE_OK; 615 return rc == TOXAV_ERR_BIT_RATE_OK;
619} 616}
620 617
621void toxav_callback_audio_bitrate_control(ToxAV* av, toxav_audio_bitrate_control_cb* function, void* user_data) 618void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status_cb* function, void* user_data)
622{ 619{
623 pthread_mutex_lock(av->mutex); 620 pthread_mutex_lock(av->mutex);
624 av->abcb.first = function; 621 av->abcb.first = function;
@@ -636,7 +633,7 @@ bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_
636 goto END; 633 goto END;
637 } 634 }
638 635
639 if (audio_bitrate_invalid(audio_bit_rate)) { 636 if (audio_bit_rate_invalid(audio_bit_rate)) {
640 rc = TOXAV_ERR_BIT_RATE_INVALID; 637 rc = TOXAV_ERR_BIT_RATE_INVALID;
641 goto END; 638 goto END;
642 } 639 }
@@ -662,7 +659,7 @@ bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_
662 call->audio_bit_rate = audio_bit_rate; 659 call->audio_bit_rate = audio_bit_rate;
663 660
664 if (!force && av->abcb.first) 661 if (!force && av->abcb.first)
665 av->abcb.first (av, call->friend_id, true, audio_bit_rate, av->abcb.second); 662 av->abcb.first (av, call->friend_number, true, audio_bit_rate, av->abcb.second);
666 } 663 }
667 664
668 pthread_mutex_unlock(call->mutex); 665 pthread_mutex_unlock(call->mutex);
@@ -897,11 +894,11 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
897 } 894 }
898 895
899 896
900 /* For bitrate measurement; send dummy packet */ 897 /* For bit rate measurement; send dummy packet */
901 if (ba_shoud_send_dummy(&call->aba)) { 898 if (ba_shoud_send_dummy(&call->aba)) {
902 sampling_rate = ntohl(sampling_rate); 899 sampling_rate = ntohl(sampling_rate);
903 if (ac_reconfigure_test_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) { 900 if (ac_reconfigure_test_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
904 /* FIXME should the bitrate changing fail here? */ 901 /* FIXME should the bit rate changing fail here? */
905 pthread_mutex_unlock(call->mutex_audio); 902 pthread_mutex_unlock(call->mutex_audio);
906 rc = TOXAV_ERR_SEND_FRAME_INVALID; 903 rc = TOXAV_ERR_SEND_FRAME_INVALID;
907 goto END; 904 goto END;
@@ -966,7 +963,7 @@ int callback_invite(void* toxav_inst, MSICall* call)
966 ToxAV* toxav = toxav_inst; 963 ToxAV* toxav = toxav_inst;
967 pthread_mutex_lock(toxav->mutex); 964 pthread_mutex_lock(toxav->mutex);
968 965
969 ToxAVCall* av_call = call_new(toxav, call->friend_id, NULL); 966 ToxAVCall* av_call = call_new(toxav, call->friend_number, NULL);
970 if (av_call == NULL) { 967 if (av_call == NULL) {
971 LOGGER_WARNING("Failed to initialize call..."); 968 LOGGER_WARNING("Failed to initialize call...");
972 pthread_mutex_unlock(toxav->mutex); 969 pthread_mutex_unlock(toxav->mutex);
@@ -977,7 +974,7 @@ int callback_invite(void* toxav_inst, MSICall* call)
977 av_call->msi_call = call; 974 av_call->msi_call = call;
978 975
979 if (toxav->ccb.first) 976 if (toxav->ccb.first)
980 toxav->ccb.first(toxav, call->friend_id, call->peer_capabilities & msi_CapSAudio, 977 toxav->ccb.first(toxav, call->friend_number, call->peer_capabilities & msi_CapSAudio,
981 call->peer_capabilities & msi_CapSVideo, toxav->ccb.second); 978 call->peer_capabilities & msi_CapSVideo, toxav->ccb.second);
982 979
983 pthread_mutex_unlock(toxav->mutex); 980 pthread_mutex_unlock(toxav->mutex);
@@ -989,7 +986,7 @@ int callback_start(void* toxav_inst, MSICall* call)
989 ToxAV* toxav = toxav_inst; 986 ToxAV* toxav = toxav_inst;
990 pthread_mutex_lock(toxav->mutex); 987 pthread_mutex_lock(toxav->mutex);
991 988
992 ToxAVCall* av_call = call_get(toxav, call->friend_id); 989 ToxAVCall* av_call = call_get(toxav, call->friend_number);
993 990
994 if (av_call == NULL) { 991 if (av_call == NULL) {
995 /* Should this ever happen? */ 992 /* Should this ever happen? */
@@ -1004,7 +1001,7 @@ int callback_start(void* toxav_inst, MSICall* call)
1004 return -1; 1001 return -1;
1005 } 1002 }
1006 1003
1007 invoke_call_state(toxav, call->friend_id, call->peer_capabilities); 1004 invoke_call_state(toxav, call->friend_number, call->peer_capabilities);
1008 1005
1009 pthread_mutex_unlock(toxav->mutex); 1006 pthread_mutex_unlock(toxav->mutex);
1010 return 0; 1007 return 0;
@@ -1015,7 +1012,7 @@ int callback_end(void* toxav_inst, MSICall* call)
1015 ToxAV* toxav = toxav_inst; 1012 ToxAV* toxav = toxav_inst;
1016 pthread_mutex_lock(toxav->mutex); 1013 pthread_mutex_lock(toxav->mutex);
1017 1014
1018 invoke_call_state(toxav, call->friend_id, TOXAV_CALL_STATE_END); 1015 invoke_call_state(toxav, call->friend_number, TOXAV_CALL_STATE_END);
1019 1016
1020 call_kill_transmission(call->av_call); 1017 call_kill_transmission(call->av_call);
1021 call_remove(call->av_call); 1018 call_remove(call->av_call);
@@ -1029,7 +1026,7 @@ int callback_error(void* toxav_inst, MSICall* call)
1029 ToxAV* toxav = toxav_inst; 1026 ToxAV* toxav = toxav_inst;
1030 pthread_mutex_lock(toxav->mutex); 1027 pthread_mutex_lock(toxav->mutex);
1031 1028
1032 invoke_call_state(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR); 1029 invoke_call_state(toxav, call->friend_number, TOXAV_CALL_STATE_ERROR);
1033 1030
1034 call_kill_transmission(call->av_call); 1031 call_kill_transmission(call->av_call);
1035 call_remove(call->av_call); 1032 call_remove(call->av_call);
@@ -1043,21 +1040,21 @@ int callback_capabilites(void* toxav_inst, MSICall* call)
1043 ToxAV* toxav = toxav_inst; 1040 ToxAV* toxav = toxav_inst;
1044 pthread_mutex_lock(toxav->mutex); 1041 pthread_mutex_lock(toxav->mutex);
1045 1042
1046 invoke_call_state(toxav, call->friend_id, call->peer_capabilities); 1043 invoke_call_state(toxav, call->friend_number, call->peer_capabilities);
1047 1044
1048 pthread_mutex_unlock(toxav->mutex); 1045 pthread_mutex_unlock(toxav->mutex);
1049 return 0; 1046 return 0;
1050} 1047}
1051 1048
1052bool audio_bitrate_invalid(uint32_t bitrate) 1049bool audio_bit_rate_invalid(uint32_t bit_rate)
1053{ 1050{
1054 /* Opus RFC 6716 section-2.1.1 dictates the following: 1051 /* Opus RFC 6716 section-2.1.1 dictates the following:
1055 * Opus supports all bitrates from 6 kbit/s to 510 kbit/s. 1052 * Opus supports all bit rates from 6 kbit/s to 510 kbit/s.
1056 */ 1053 */
1057 return bitrate < 6 || bitrate > 510; 1054 return bit_rate < 6 || bit_rate > 510;
1058} 1055}
1059 1056
1060bool video_bitrate_invalid(uint32_t bitrate) 1057bool video_bit_rate_invalid(uint32_t bit_rate)
1061{ 1058{
1062 /* TODO: If anyone knows the answer to this one please fill it up */ 1059 /* TODO: If anyone knows the answer to this one please fill it up */
1063 return false; 1060 return false;
@@ -1099,7 +1096,7 @@ ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error)
1099 } 1096 }
1100 1097
1101 call->av = av; 1098 call->av = av;
1102 call->friend_id = friend_number; 1099 call->friend_number = friend_number;
1103 1100
1104 if (av->calls == NULL) { /* Creating */ 1101 if (av->calls == NULL) { /* Creating */
1105 av->calls = calloc (sizeof(ToxAVCall*), friend_number + 1); 1102 av->calls = calloc (sizeof(ToxAVCall*), friend_number + 1);
@@ -1126,7 +1123,7 @@ ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error)
1126 av->calls = tmp; 1123 av->calls = tmp;
1127 1124
1128 /* Set fields in between to null */ 1125 /* Set fields in between to null */
1129 int32_t i = av->calls_tail; 1126 int32_t i = av->calls_tail + 1;
1130 for (; i < friend_number; i ++) 1127 for (; i < friend_number; i ++)
1131 av->calls[i] = NULL; 1128 av->calls[i] = NULL;
1132 1129
@@ -1164,7 +1161,7 @@ void call_remove(ToxAVCall* call)
1164 if (call == NULL) 1161 if (call == NULL)
1165 return; 1162 return;
1166 1163
1167 uint32_t friend_id = call->friend_id; 1164 uint32_t friend_number = call->friend_number;
1168 ToxAV* av = call->av; 1165 ToxAV* av = call->av;
1169 1166
1170 ToxAVCall* prev = call->prev; 1167 ToxAVCall* prev = call->prev;
@@ -1175,16 +1172,16 @@ void call_remove(ToxAVCall* call)
1175 if (prev) 1172 if (prev)
1176 prev->next = next; 1173 prev->next = next;
1177 else if (next) 1174 else if (next)
1178 av->calls_head = next->friend_id; 1175 av->calls_head = next->friend_number;
1179 else goto CLEAR; 1176 else goto CLEAR;
1180 1177
1181 if (next) 1178 if (next)
1182 next->prev = prev; 1179 next->prev = prev;
1183 else if (prev) 1180 else if (prev)
1184 av->calls_tail = prev->friend_id; 1181 av->calls_tail = prev->friend_number;
1185 else goto CLEAR; 1182 else goto CLEAR;
1186 1183
1187 av->calls[friend_id] = NULL; 1184 av->calls[friend_number] = NULL;
1188 return; 1185 return;
1189 1186
1190CLEAR: 1187CLEAR:
@@ -1214,17 +1211,16 @@ bool call_prepare_transmission(ToxAVCall* call)
1214 if (create_recursive_mutex(call->mutex_audio) != 0) 1211 if (create_recursive_mutex(call->mutex_audio) != 0)
1215 return false; 1212 return false;
1216 1213
1217 if (create_recursive_mutex(call->mutex_video) != 0) { 1214 if (create_recursive_mutex(call->mutex_video) != 0)
1218 goto AUDIO_SENDING_MUTEX_CLEANUP; 1215 goto FAILURE_3;
1219 } 1216
1217 if (create_recursive_mutex(call->mutex) != 0)
1218 goto FAILURE_2;
1220 1219
1221 if (create_recursive_mutex(call->mutex) != 0) {
1222 goto VIDEO_SENDING_MUTEX_CLEANUP;
1223 }
1224 1220
1225 { /* Prepare audio */ 1221 { /* Prepare audio */
1226 call->audio.second = ac_new(av, call->friend_id, av->acb.first, av->acb.second); 1222 call->audio.second = ac_new(av, call->friend_number, av->acb.first, av->acb.second);
1227 call->audio.first = rtp_new(rtp_TypeAudio, av->m, call->friend_id, call->audio.second, ac_queue_message); 1223 call->audio.first = rtp_new(rtp_TypeAudio, av->m, call->friend_number, call->audio.second, ac_queue_message);
1228 1224
1229 if ( !call->audio.first || !call->audio.second ) { 1225 if ( !call->audio.first || !call->audio.second ) {
1230 LOGGER_ERROR("Error while starting audio!\n"); 1226 LOGGER_ERROR("Error while starting audio!\n");
@@ -1233,8 +1229,8 @@ bool call_prepare_transmission(ToxAVCall* call)
1233 } 1229 }
1234 1230
1235 { /* Prepare video */ 1231 { /* Prepare video */
1236 call->video.second = vc_new(av, call->friend_id, av->vcb.first, av->vcb.second, call->msi_call->peer_vfpsz); 1232 call->video.second = vc_new(av, call->friend_number, av->vcb.first, av->vcb.second, call->msi_call->peer_vfpsz);
1237 call->video.first = rtp_new(rtp_TypeVideo, av->m, call->friend_id, call->video.second, vc_queue_message); 1233 call->video.first = rtp_new(rtp_TypeVideo, av->m, call->friend_number, call->video.second, vc_queue_message);
1238 1234
1239 if ( !call->video.first || !call->video.second ) { 1235 if ( !call->video.first || !call->video.second ) {
1240 LOGGER_ERROR("Error while starting video!\n"); 1236 LOGGER_ERROR("Error while starting video!\n");
@@ -1255,9 +1251,9 @@ FAILURE:
1255 call->video.first = NULL; 1251 call->video.first = NULL;
1256 call->video.second = NULL; 1252 call->video.second = NULL;
1257 pthread_mutex_destroy(call->mutex); 1253 pthread_mutex_destroy(call->mutex);
1258VIDEO_SENDING_MUTEX_CLEANUP: 1254FAILURE_2:
1259 pthread_mutex_destroy(call->mutex_video); 1255 pthread_mutex_destroy(call->mutex_video);
1260AUDIO_SENDING_MUTEX_CLEANUP: 1256FAILURE_3:
1261 pthread_mutex_destroy(call->mutex_audio); 1257 pthread_mutex_destroy(call->mutex_audio);
1262 return false; 1258 return false;
1263} 1259}
diff --git a/toxav/toxav.h b/toxav/toxav.h
index f2c3b2b3..b8db223e 100644
--- a/toxav/toxav.h
+++ b/toxav/toxav.h
@@ -333,23 +333,23 @@ typedef enum TOXAV_ERR_BIT_RATE {
333 TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL 333 TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL
334} TOXAV_ERR_BIT_RATE; 334} TOXAV_ERR_BIT_RATE;
335/** 335/**
336 * The function type for the `audio_bitrate_control` callback. 336 * The function type for the `audio_bit_rate_status` callback.
337 * 337 *
338 * @param friend_number The friend number of the friend for which to set the 338 * @param friend_number The friend number of the friend for which to set the
339 * audio bit rate. 339 * audio bit rate.
340 * @param good Is the stream good enough to keep the said bitrate. Upon failed 340 * @param stable Is the stream stable enough to keep the bit rate.
341 * non forceful bit rate setup this will be set to false and 'bit_rate' 341 * Upon successful, non forceful, bit rate change, this is set to
342 * will be set to the bit rate that failed, otherwise 'good' will be set to 342 * true and 'bit_rate' is set to new bit rate.
343 * true with 'bit_rate' set to new bit rate. If the stream becomes bad, 343 * The stable is set to false with bit_rate set to the unstable
344 * the 'good' wil be set to false with 'bit_rate' set to the current bit rate. 344 * bit rate when either current stream is unstable with said bit rate
345 * This callback will never be called when the stream is good. 345 * or the non forceful change failed.
346 * @param bit_rate The bit rate in Kb/sec. 346 * @param bit_rate The bit rate in Kb/sec.
347 */ 347 */
348typedef void toxav_audio_bitrate_control_cb(ToxAV *av, uint32_t friend_number, bool good, uint32_t bit_rate, void *user_data); 348typedef void toxav_audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data);
349/** 349/**
350 * Set the callback for the `audio_bitrate_control` event. Pass NULL to unset. 350 * Set the callback for the `audio_bit_rate_status` event. Pass NULL to unset.
351 */ 351 */
352void toxav_callback_audio_bitrate_control(ToxAV *av, toxav_audio_bitrate_control_cb *function, void *user_data); 352void toxav_callback_audio_bit_rate_status(ToxAV *av, toxav_audio_bit_rate_status_cb *function, void *user_data);
353/** 353/**
354 * Set the audio bit rate to be used in subsequent audio frames. 354 * Set the audio bit rate to be used in subsequent audio frames.
355 * 355 *
@@ -362,23 +362,23 @@ void toxav_callback_audio_bitrate_control(ToxAV *av, toxav_audio_bitrate_control
362 */ 362 */
363bool toxav_set_audio_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); 363bool toxav_set_audio_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error);
364/** 364/**
365 * The function type for the `video_bitrate_control` callback. 365 * The function type for the `video_bit_rate_status` callback.
366 * 366 *
367 * @param friend_number The friend number of the friend for which to set the 367 * @param friend_number The friend number of the friend for which to set the
368 * video bit rate. 368 * video bit rate.
369 * @param good Is the stream good enough to keep the said bitrate. Upon failed 369 * @param stable Is the stream stable enough to keep the bit rate.
370 * non forceful bit rate setup this will be set to false and 'bit_rate' 370 * Upon successful, non forceful, bit rate change, this is set to
371 * will be set to the bit rate that failed, otherwise 'good' will be set to 371 * true and 'bit_rate' is set to new bit rate.
372 * true with 'bit_rate' set to new bit rate. If the stream becomes bad, 372 * The stable is set to false with bit_rate set to the unstable
373 * the 'good' wil be set to false with 'bit_rate' set to the current bit rate. 373 * bit rate when either current stream is unstable with said bit rate
374 * This callback will never be called when the stream is good. 374 * or the non forceful change failed.
375 * @param bit_rate The bit rate in Kb/sec. 375 * @param bit_rate The bit rate in Kb/sec.
376 */ 376 */
377typedef void toxav_video_bitrate_control_cb(ToxAV *av, uint32_t friend_number, bool good, uint32_t bit_rate, void *user_data); 377typedef void toxav_video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data);
378/** 378/**
379 * Set the callback for the `video_bitrate_control` event. Pass NULL to unset. 379 * Set the callback for the `video_bit_rate_status` event. Pass NULL to unset.
380 */ 380 */
381void toxav_callback_video_bitrate_control(ToxAV *av, toxav_video_bitrate_control_cb *function, void *user_data); 381void toxav_callback_video_bit_rate_status(ToxAV *av, toxav_video_bit_rate_status_cb *function, void *user_data);
382/** 382/**
383 * Set the video bit rate to be used in subsequent video frames. 383 * Set the video bit rate to be used in subsequent video frames.
384 * 384 *
diff --git a/toxav/video.c b/toxav/video.c
index c540af3b..22ca2bee 100644
--- a/toxav/video.c
+++ b/toxav/video.c
@@ -35,15 +35,14 @@
35#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */ 35#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */
36#define VIDEOFRAME_HEADER_SIZE 0x2 36#define VIDEOFRAME_HEADER_SIZE 0x2
37 37
38/* FIXME: Might not be enough? NOTE: I think it is enough */
39#define VIDEO_DECODE_BUFFER_SIZE 20 38#define VIDEO_DECODE_BUFFER_SIZE 20
40 39
41typedef struct { uint16_t size; uint8_t data[]; } Payload; 40typedef struct { uint16_t size; uint8_t data[]; } Payload;
42 41
43bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bitrate); 42bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate);
44 43
45 44
46VCSession* vc_new(ToxAV* av, uint32_t friend_id, toxav_receive_video_frame_cb* cb, void* cb_data, uint32_t mvfpsz) 45VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb* cb, void* cb_data, uint32_t mvfpsz)
47{ 46{
48 VCSession *vc = calloc(sizeof(VCSession), 1); 47 VCSession *vc = calloc(sizeof(VCSession), 1);
49 48
@@ -86,7 +85,7 @@ VCSession* vc_new(ToxAV* av, uint32_t friend_id, toxav_receive_video_frame_cb* c
86 vc->lcfd = 60; 85 vc->lcfd = 60;
87 vc->vcb.first = cb; 86 vc->vcb.first = cb;
88 vc->vcb.second = cb_data; 87 vc->vcb.second = cb_data;
89 vc->friend_id = friend_id; 88 vc->friend_number = friend_number;
90 vc->peer_video_frame_piece_size = mvfpsz; 89 vc->peer_video_frame_piece_size = mvfpsz;
91 90
92 return vc; 91 return vc;
@@ -140,7 +139,7 @@ void vc_do(VCSession* vc)
140 /* Play decoded images */ 139 /* Play decoded images */
141 for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) { 140 for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) {
142 if (vc->vcb.first) 141 if (vc->vcb.first)
143 vc->vcb.first(vc->av, vc->friend_id, dest->d_w, dest->d_h, 142 vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h,
144 (const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1], (const uint8_t*)dest->planes[2], 143 (const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1], (const uint8_t*)dest->planes[2],
145 dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb.second); 144 dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb.second);
146 145
@@ -289,16 +288,16 @@ end:
289 rtp_free_msg(msg); 288 rtp_free_msg(msg);
290 return 0; 289 return 0;
291} 290}
292int vc_reconfigure_encoder(VCSession* vc, int32_t bitrate, uint16_t width, uint16_t height) 291int vc_reconfigure_encoder(VCSession* vc, int32_t bit_rate, uint16_t width, uint16_t height)
293{ 292{
294 if (!vc) 293 if (!vc)
295 return -1; 294 return -1;
296 295
297 vpx_codec_enc_cfg_t cfg = *vc->encoder->config.enc; 296 vpx_codec_enc_cfg_t cfg = *vc->encoder->config.enc;
298 if (cfg.rc_target_bitrate == bitrate && cfg.g_w == width && cfg.g_h == height) 297 if (cfg.rc_target_bitrate == bit_rate && cfg.g_w == width && cfg.g_h == height)
299 return 0; /* Nothing changed */ 298 return 0; /* Nothing changed */
300 299
301 cfg.rc_target_bitrate = bitrate; 300 cfg.rc_target_bitrate = bit_rate;
302 cfg.g_w = width; 301 cfg.g_w = width;
303 cfg.g_h = height; 302 cfg.g_h = height;
304 303
@@ -310,16 +309,16 @@ int vc_reconfigure_encoder(VCSession* vc, int32_t bitrate, uint16_t width, uint1
310 309
311 return 0; 310 return 0;
312} 311}
313int vc_reconfigure_test_encoder(VCSession* vc, int32_t bitrate, uint16_t width, uint16_t height) 312int vc_reconfigure_test_encoder(VCSession* vc, int32_t bit_rate, uint16_t width, uint16_t height)
314{ 313{
315 if (!vc) 314 if (!vc)
316 return -1; 315 return -1;
317 316
318 vpx_codec_enc_cfg_t cfg = *vc->test_encoder->config.enc; 317 vpx_codec_enc_cfg_t cfg = *vc->test_encoder->config.enc;
319 if (cfg.rc_target_bitrate == bitrate && cfg.g_w == width && cfg.g_h == height) 318 if (cfg.rc_target_bitrate == bit_rate && cfg.g_w == width && cfg.g_h == height)
320 return 0; /* Nothing changed */ 319 return 0; /* Nothing changed */
321 320
322 cfg.rc_target_bitrate = bitrate; 321 cfg.rc_target_bitrate = bit_rate;
323 cfg.g_w = width; 322 cfg.g_w = width;
324 cfg.g_h = height; 323 cfg.g_h = height;
325 324
@@ -334,7 +333,7 @@ int vc_reconfigure_test_encoder(VCSession* vc, int32_t bitrate, uint16_t width,
334 333
335 334
336 335
337bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bitrate) 336bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate)
338{ 337{
339 assert(dest); 338 assert(dest);
340 339
@@ -354,7 +353,7 @@ bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bitrate)
354 return false; 353 return false;
355 } 354 }
356 355
357 cfg.rc_target_bitrate = bitrate; 356 cfg.rc_target_bitrate = bit_rate;
358 cfg.g_w = 800; 357 cfg.g_w = 800;
359 cfg.g_h = 600; 358 cfg.g_h = 600;
360 cfg.g_pass = VPX_RC_ONE_PASS; 359 cfg.g_pass = VPX_RC_ONE_PASS;
diff --git a/toxav/video.h b/toxav/video.h
index 78003ef3..8da15578 100644
--- a/toxav/video.h
+++ b/toxav/video.h
@@ -38,6 +38,9 @@
38 38
39struct RTPMessage_s; 39struct RTPMessage_s;
40 40
41/*
42 * Base Video Codec session type.
43 */
41typedef struct VCSession_s { 44typedef struct VCSession_s {
42 45
43 /* encoding */ 46 /* encoding */
@@ -65,23 +68,46 @@ typedef struct VCSession_s {
65 const uint8_t *processing_video_frame; 68 const uint8_t *processing_video_frame;
66 uint16_t processing_video_frame_size; 69 uint16_t processing_video_frame_size;
67 70
68
69 ToxAV *av; 71 ToxAV *av;
70 int32_t friend_id; 72 uint32_t friend_number;
71 73
72 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ 74 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */
73 75
74 pthread_mutex_t queue_mutex[1]; 76 pthread_mutex_t queue_mutex[1];
75} VCSession; 77} VCSession;
76 78
77VCSession* vc_new(ToxAV* av, uint32_t friend_id, toxav_receive_video_frame_cb *cb, void *cb_data, uint32_t mvfpsz); 79/*
80 * Create new Video Codec session.
81 */
82VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb *cb, void *cb_data, uint32_t mvfpsz);
83/*
84 * Kill the Video Codec session.
85 */
78void vc_kill(VCSession* vc); 86void vc_kill(VCSession* vc);
87/*
88 * Do periodic work. Work is consisted out of decoding only.
89 */
79void vc_do(VCSession* vc); 90void vc_do(VCSession* vc);
91/*
92 * Set new video splitting cycle. This is requirement in order to send video packets.
93 */
80void vc_init_video_splitter_cycle(VCSession* vc); 94void vc_init_video_splitter_cycle(VCSession* vc);
95/*
96 * Update the video splitter cycle with new data.
97 */
81int vc_update_video_splitter_cycle(VCSession* vc, const uint8_t* payload, uint16_t length); 98int vc_update_video_splitter_cycle(VCSession* vc, const uint8_t* payload, uint16_t length);
99/*
100 * Iterate over splitted cycle.
101 */
82const uint8_t *vc_iterate_split_video_frame(VCSession* vc, uint16_t *size); 102const uint8_t *vc_iterate_split_video_frame(VCSession* vc, uint16_t *size);
103/*
104 * Queue new rtp message.
105 */
83int vc_queue_message(void *vcp, struct RTPMessage_s *msg); 106int vc_queue_message(void *vcp, struct RTPMessage_s *msg);
84int vc_reconfigure_encoder(VCSession* vc, int32_t bitrate, uint16_t width, uint16_t height); 107/*
85int vc_reconfigure_test_encoder(VCSession* vc, int32_t bitrate, uint16_t width, uint16_t height); 108 * Set new values to the encoders.
109 */
110int vc_reconfigure_encoder(VCSession* vc, int32_t bit_rate, uint16_t width, uint16_t height);
111int vc_reconfigure_test_encoder(VCSession* vc, int32_t bit_rate, uint16_t width, uint16_t height);
86 112
87#endif /* VIDEO_H */ \ No newline at end of file 113#endif /* VIDEO_H */ \ No newline at end of file