summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-03-28 03:36:31 +0100
committermannol <eniz_vukovic@hotmail.com>2015-03-28 03:36:31 +0100
commite65efc8936ee029f735a22105843335c18026ad2 (patch)
tree8a0d832ced409e035946c6a05e548ddeea3668cb
parent9bd20e874141640ed592b2a1ac32e96f57c12510 (diff)
Improvement in test and removed some bloat from CS
-rw-r--r--toxav/Makefile.inc1
-rw-r--r--toxav/av_test.c602
-rw-r--r--toxav/codec.c187
-rw-r--r--toxav/codec.h16
-rw-r--r--toxav/toxav.c11
5 files changed, 327 insertions, 490 deletions
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc
index 1dbabbcd..8e2be25e 100644
--- a/toxav/Makefile.inc
+++ b/toxav/Makefile.inc
@@ -52,6 +52,7 @@ av_test_LDADD = $(LIBSODIUM_LDFLAGS) \
52 $(NACL_OBJECTS) \ 52 $(NACL_OBJECTS) \
53 -lopenal \ 53 -lopenal \
54 -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 \ 54 -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 \
55 -lsndfile \
55 $(NACL_LIBS) 56 $(NACL_LIBS)
56 57
57 58
diff --git a/toxav/av_test.c b/toxav/av_test.c
index 249e0ab7..5ca53eb9 100644
--- a/toxav/av_test.c
+++ b/toxav/av_test.c
@@ -1,35 +1,32 @@
1#include "toxav.h" 1#include "toxav.h"
2#include "../toxcore/tox.h" 2#include "../toxcore/tox.h"
3 3
4#ifdef __APPLE__ 4/* For playing audio data */
5# include <OpenAL/al.h> 5#include <AL/al.h>
6# include <OpenAL/alc.h> 6#include <AL/alc.h>
7#else
8# include <AL/al.h>
9# include <AL/alc.h>
10/* compatibility with older versions of OpenAL */
11# ifndef ALC_ALL_DEVICES_SPECIFIER
12# include <AL/alext.h>
13# endif /* ALC_ALL_DEVICES_SPECIFIER */
14#endif /* __APPLE__ */
15 7
8/* Processing wav's */
9#include <sndfile.h>
10
11/* For reading and displaying video data */
16#include <opencv/cv.h> 12#include <opencv/cv.h>
17#include <opencv/highgui.h> 13#include <opencv/highgui.h>
18 14
15/* For converting images TODO remove */
19#include <vpx/vpx_image.h> 16#include <vpx/vpx_image.h>
20 17
18
19#include <sys/stat.h>
21#include <assert.h> 20#include <assert.h>
22#include <stdio.h> 21#include <stdio.h>
23#include <stdlib.h> 22#include <stdlib.h>
24#include <time.h> 23#include <time.h>
25#include <string.h> 24#include <string.h>
26 25#include <errno.h>
27#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
28#define c_sleep(x) Sleep(1*x)
29#else
30#include <unistd.h> 26#include <unistd.h>
27
28
31#define c_sleep(x) usleep(1000*x) 29#define c_sleep(x) usleep(1000*x)
32#endif
33 30
34 31
35/* Enable/disable tests */ 32/* Enable/disable tests */
@@ -39,17 +36,17 @@
39#define TEST_REJECT 0 36#define TEST_REJECT 0
40#define TEST_CANCEL 0 37#define TEST_CANCEL 0
41#define TEST_MUTE_UNMUTE 0 38#define TEST_MUTE_UNMUTE 0
42#define TEST_TRANSFER_A 0 39#define TEST_TRANSFER_A 1
43#define TEST_TRANSFER_V 1 40#define TEST_TRANSFER_V 0
44 41
45 42
46typedef struct { 43typedef struct {
47 bool incoming; 44 bool incoming;
48 uint32_t state; 45 uint32_t state;
49 uint32_t output_source;
50} CallControl; 46} CallControl;
51 47
52const char* video_test_window = "AV Test"; 48const char* vdout = "AV Test";
49uint32_t adout;
53 50
54const char* stringify_state(TOXAV_CALL_STATE s) 51const char* stringify_state(TOXAV_CALL_STATE s)
55{ 52{
@@ -65,10 +62,7 @@ const char* stringify_state(TOXAV_CALL_STATE s)
65 }; 62 };
66 63
67 return strings [s]; 64 return strings [s];
68}; 65}
69
70
71int device_play_frame(uint32_t source, const int16_t* PCM, size_t size);
72 66
73/** 67/**
74 * Callbacks 68 * Callbacks
@@ -104,9 +98,11 @@ void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
104 const uint8_t* vData = planes[VPX_PLANE_U]; 98 const uint8_t* vData = planes[VPX_PLANE_U];
105 99
106 // convert from planar to packed 100 // convert from planar to packed
107 for (int y = 0; y < height; ++y) 101 int y = 0;
102 for (; y < height; ++y)
108 { 103 {
109 for (int x = 0; x < width; ++x) 104 int x = 0;
105 for (; x < width; ++x)
110 { 106 {
111 uint8_t Y = planes[VPX_PLANE_Y][x + y * bpl]; 107 uint8_t Y = planes[VPX_PLANE_Y][x + y * bpl];
112 uint8_t U = planes[VPX_PLANE_V][x/(1 << 1) + y/(1 << 1)*cxbpl]; 108 uint8_t U = planes[VPX_PLANE_V][x/(1 << 1) + y/(1 << 1)*cxbpl];
@@ -117,7 +113,7 @@ void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
117 } 113 }
118 } 114 }
119 115
120 cvShowImage(video_test_window, &output_img); 116 cvShowImage(vdout, &output_img);
121 free(output_img.imageData); 117 free(output_img.imageData);
122} 118}
123void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, 119void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
@@ -127,7 +123,32 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
127 uint32_t sampling_rate, 123 uint32_t sampling_rate,
128 void *user_data) 124 void *user_data)
129{ 125{
130 device_play_frame(((CallControl*)user_data)->output_source, pcm, sample_count); 126 uint32_t bufid;
127 int32_t processed, queued;
128 alGetSourcei(adout, AL_BUFFERS_PROCESSED, &processed);
129 alGetSourcei(adout, AL_BUFFERS_QUEUED, &queued);
130
131 if(processed) {
132 uint32_t bufids[processed];
133 alSourceUnqueueBuffers(adout, processed, bufids);
134 alDeleteBuffers(processed - 1, bufids + 1);
135 bufid = bufids[0];
136 }
137// else if(queued < 16)
138 alGenBuffers(1, &bufid);
139// else
140// return;
141
142
143 alBufferData(bufid, channels == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
144 pcm, sample_count * channels * 2, sampling_rate);
145 alSourceQueueBuffers(adout, 1, &bufid);
146
147 int32_t state;
148 alGetSourcei(adout, AL_SOURCE_STATE, &state);
149
150 if(state != AL_PLAYING)
151 alSourcePlay(adout);
131} 152}
132void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) 153void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata)
133{ 154{
@@ -139,8 +160,20 @@ void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t
139 160
140/** 161/**
141 */ 162 */
142void prepare(Tox* Bsn, Tox* Alice, Tox* Bob) 163void initialize_tox(Tox** bootstrap, ToxAV** AliceAV, CallControl* AliceCC, ToxAV** BobAV, CallControl* BobCC)
143{ 164{
165 Tox* Alice;
166 Tox* Bob;
167
168 *bootstrap = tox_new(0);
169 Alice = tox_new(0);
170 Bob = tox_new(0);
171
172 assert(bootstrap && Alice && Bob);
173
174 printf("Created 3 instances of Tox\n");
175
176 printf("Preparing network...\n");
144 long long unsigned int cur_time = time(NULL); 177 long long unsigned int cur_time = time(NULL);
145 178
146 uint32_t to_compare = 974536; 179 uint32_t to_compare = 974536;
@@ -154,11 +187,11 @@ void prepare(Tox* Bsn, Tox* Alice, Tox* Bob)
154 uint8_t off = 1; 187 uint8_t off = 1;
155 188
156 while (1) { 189 while (1) {
157 tox_do(Bsn); 190 tox_do(*bootstrap);
158 tox_do(Alice); 191 tox_do(Alice);
159 tox_do(Bob); 192 tox_do(Bob);
160 193
161 if (tox_isconnected(Bsn) && tox_isconnected(Alice) && tox_isconnected(Bob) && off) { 194 if (tox_isconnected(*bootstrap) && tox_isconnected(Alice) && tox_isconnected(Bob) && off) {
162 printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); 195 printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time);
163 off = 0; 196 off = 0;
164 } 197 }
@@ -169,25 +202,32 @@ void prepare(Tox* Bsn, Tox* Alice, Tox* Bob)
169 c_sleep(20); 202 c_sleep(20);
170 } 203 }
171 204
172 printf("All set after %llu seconds!\n", time(NULL) - cur_time); 205
173} 206 TOXAV_ERR_NEW rc;
174void prepareAV(ToxAV* AliceAV, void* AliceUD, ToxAV* BobAV, void* BobUD) 207 *AliceAV = toxav_new(Alice, &rc);
175{ 208 assert(rc == TOXAV_ERR_NEW_OK);
209
210 *BobAV = toxav_new(Bob, &rc);
211 assert(rc == TOXAV_ERR_NEW_OK);
212
176 /* Alice */ 213 /* Alice */
177 toxav_callback_call(AliceAV, t_toxav_call_cb, AliceUD); 214 toxav_callback_call(*AliceAV, t_toxav_call_cb, AliceCC);
178 toxav_callback_call_state(AliceAV, t_toxav_call_state_cb, AliceUD); 215 toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC);
179 toxav_callback_receive_video_frame(AliceAV, t_toxav_receive_video_frame_cb, AliceUD); 216 toxav_callback_receive_video_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC);
180 toxav_callback_receive_audio_frame(AliceAV, t_toxav_receive_audio_frame_cb, AliceUD); 217 toxav_callback_receive_audio_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC);
181 218
182 /* Bob */ 219 /* Bob */
183 toxav_callback_call(BobAV, t_toxav_call_cb, BobUD); 220 toxav_callback_call(*BobAV, t_toxav_call_cb, BobCC);
184 toxav_callback_call_state(BobAV, t_toxav_call_state_cb, BobUD); 221 toxav_callback_call_state(*BobAV, t_toxav_call_state_cb, BobCC);
185 toxav_callback_receive_video_frame(BobAV, t_toxav_receive_video_frame_cb, BobUD); 222 toxav_callback_receive_video_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC);
186 toxav_callback_receive_audio_frame(BobAV, t_toxav_receive_audio_frame_cb, BobUD); 223 toxav_callback_receive_audio_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC);
224
225 printf("Created 2 instances of ToxAV\n");
226 printf("All set after %llu seconds!\n", time(NULL) - cur_time);
187} 227}
188void iterate(Tox* Bsn, ToxAV* AliceAV, ToxAV* BobAV) 228int iterate_tox(Tox* bootstrap, ToxAV* AliceAV, ToxAV* BobAV)
189{ 229{
190 tox_do(Bsn); 230 tox_do(bootstrap);
191 tox_do(toxav_get_tox(AliceAV)); 231 tox_do(toxav_get_tox(AliceAV));
192 tox_do(toxav_get_tox(BobAV)); 232 tox_do(toxav_get_tox(BobAV));
193 233
@@ -197,114 +237,16 @@ void iterate(Tox* Bsn, ToxAV* AliceAV, ToxAV* BobAV)
197 int mina = MIN(tox_do_interval(toxav_get_tox(AliceAV)), toxav_iteration_interval(AliceAV)); 237 int mina = MIN(tox_do_interval(toxav_get_tox(AliceAV)), toxav_iteration_interval(AliceAV));
198 int minb = MIN(tox_do_interval(toxav_get_tox(BobAV)), toxav_iteration_interval(BobAV)); 238 int minb = MIN(tox_do_interval(toxav_get_tox(BobAV)), toxav_iteration_interval(BobAV));
199 239
200 c_sleep(MIN(mina, minb)); 240 int rc = MIN(mina, minb);
201} 241 c_sleep(rc);
202
203int device_read_frame(ALCdevice* device, int32_t frame_dur, int16_t* PCM, size_t max_size)
204{
205 int f_size = (8000 * frame_dur / 1000);
206
207 if (max_size < f_size)
208 return -1;
209
210 /* Don't block if not enough data */
211 int32_t samples;
212 alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, sizeof(int32_t), &samples);
213 if (samples < f_size)
214 return 0;
215
216 alcCaptureSamples(device, PCM, f_size);
217 return f_size;
218}
219
220int device_play_frame(uint32_t source, const int16_t* PCM, size_t size)
221{
222 uint32_t bufid;
223 int32_t processed, queued;
224 alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
225 alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
226
227 if(processed) {
228 uint32_t bufids[processed];
229 alSourceUnqueueBuffers(source, processed, bufids);
230 alDeleteBuffers(processed - 1, bufids + 1);
231 bufid = bufids[0];
232 }
233 else if(queued < 16)
234 alGenBuffers(1, &bufid);
235 else
236 return 0;
237 242
238 243 return rc;
239 alBufferData(bufid, AL_FORMAT_STEREO16, PCM, size * 2 * 2, 48000);
240 alSourceQueueBuffers(source, 1, &bufid);
241
242 int32_t state;
243 alGetSourcei(source, AL_SOURCE_STATE, &state);
244
245 if(state != AL_PLAYING)
246 alSourcePlay(source);
247 return 1;
248}
249
250int print_devices()
251{
252 const char* default_input;
253 const char* default_output;
254
255 const char *device;
256
257 printf("Default input device: %s\n", alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
258 printf("Default output device: %s\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
259
260 printf("\n");
261
262 printf("Input devices:\n");
263
264 int i = 0;
265 for(device = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); *device;
266 device += strlen( device ) + 1, ++i) {
267 printf("%d) %s\n", i, device);
268 }
269
270 printf("\n");
271 printf("Output devices:\n");
272
273 i = 0;
274 for(device = alcGetString(NULL, ALC_DEVICE_SPECIFIER); *device;
275 device += strlen( device ) + 1, ++i) {
276 printf("%d) %s\n", i, device);
277 }
278
279 return 0;
280}
281
282int print_help(const char* name, int rc)
283{
284 fprintf(stderr, "Usage: %s [-h] <in device> <out device>\n", name);
285 return rc;
286}
287
288long get_device_idx(const char* arg)
289{
290 if (strcmp(arg, "-") == 0)
291 return -1; /* Default */
292
293 char *p;
294 long res = strtol(arg, &p, 10);
295
296 if (*p) {
297 fprintf(stderr, "Invalid device!");
298 exit(1);
299 }
300
301 return res;
302} 244}
303 245
304int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img) 246int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img)
305{ 247{
306 /* I use vpx image coz i'm noob TODO use opencv conversion */ 248 /* I use vpx image coz i'm noob TODO use opencv conversion */
307 vpx_image vpx_img; 249 vpx_image_t vpx_img;
308 vpx_img.w = vpx_img.h = vpx_img.d_w = vpx_img.d_h = 0; 250 vpx_img.w = vpx_img.h = vpx_img.d_w = vpx_img.d_h = 0;
309 251
310 const int w = img->width; 252 const int w = img->width;
@@ -312,9 +254,11 @@ int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img)
312 254
313 vpx_img_alloc(&vpx_img, VPX_IMG_FMT_VPXI420, w, h, 1); 255 vpx_img_alloc(&vpx_img, VPX_IMG_FMT_VPXI420, w, h, 1);
314 256
315 for (int y = 0; y < h; ++y) 257 int y = 0;
258 for (; y < h; ++y)
316 { 259 {
317 for (int x = 0; x < w; ++x) 260 int x = 0;
261 for (; x < w; ++x)
318 { 262 {
319 uint8_t b = img->imageData[(x + y * w) * 3 + 0]; 263 uint8_t b = img->imageData[(x + y * w) * 3 + 0];
320 uint8_t g = img->imageData[(x + y * w) * 3 + 1]; 264 uint8_t g = img->imageData[(x + y * w) * 3 + 1];
@@ -341,113 +285,118 @@ int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img)
341 return rc; 285 return rc;
342} 286}
343 287
344int main (int argc, char** argv) 288int print_audio_devices()
345{ 289{
346 /* AV files for testing */ 290 const char *device;
347 const char* audio_in = ""; 291
348 const char* video_in = ""; 292 printf("Default output device: %s\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
349 long audio_out_dev = 0; 293 printf("Output devices:\n");
350 294
351AGAIN: 295 int i = 0;
352 switch (getopt(argc, argv, "a:v:o:")) 296 for(device = alcGetString(NULL, ALC_DEVICE_SPECIFIER); *device;
353 { 297 device += strlen( device ) + 1, ++i) {
354 case 'a': 298 printf("%d) %s\n", i, device);
355 audio_in = optarg;
356 goto AGAIN;
357 break;
358 case 'v':
359 video_in = optarg;
360 goto AGAIN;
361 break;
362 case 'o':
363 char *d;
364 audio_out_dev = strtol(optarg, &d, 10);
365 if (*d) {
366 fprintf(stderr, "Invalid value for argument: 'o'");
367 return 1;
368 }
369 goto AGAIN;
370 break;
371 case '?':
372 return 1;
373 break;
374 case -1:
375 break;
376 } 299 }
377 300
378 301 return 0;
302}
303
304int print_help (const char* name)
305{
306 printf("Usage: %s -[a:v:o:dh]\n"
307 "-a <path> video input file\n"
308 "-v <path> video input file\n"
309 "-o <idx> output audio device index\n"
310 "-d print output audio devices\n"
311 "-h print this help\n", name);
379 312
380 return 0; 313 return 0;
314}
315
316int main (int argc, char** argv)
317{
318 struct stat st;
381 319
382 if (argc == 2) { 320 /* AV files for testing */
383 if (strcmp(argv[1], "-d") == 0 || strcmp(argv[1], "--devices") == 0) { 321 const char* af_name = NULL;
384 return print_devices(); 322 const char* vf_name = NULL;
385 } 323 long audio_out_dev_idx = 0;
386 if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { 324
387 return print_help(argv[0], 0); 325 /* Pasre settings */
388 } 326 CHECK_ARG: switch (getopt(argc, argv, "a:v:o:dh")) {
389 } 327 case 'a':
390 328 af_name = optarg;
391 if (argc != 3) { 329 goto CHECK_ARG;
392 fprintf(stderr, "Invalid input!\n"); 330 case 'v':
393 return print_help(argv[0], 1); 331 vf_name = optarg;
394 } 332 goto CHECK_ARG;
395 333 case 'o': {
396 int i; 334 char *d;
397 335 audio_out_dev_idx = strtol(optarg, &d, 10);
398 const char* in_device_name = ""; 336 if (*d) {
399 const char* out_device_name = ""; 337 printf("Invalid value for argument: 'o'");
400 338 exit(1);
401 { 339 }
402 long dev = get_device_idx(argv[1]); 340 goto CHECK_ARG;
403 if (dev == -1) 341 }
404 in_device_name = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); 342 case 'd':
405 else 343 return print_audio_devices();
406 { 344 case 'h':
407 const char* tmp; 345 return print_help(argv[0]);
408 i = -1; 346 case '?':
409 for(tmp = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); *tmp && i != dev; 347 exit(1);
410 tmp += strlen( tmp ) + 1, ++i) 348 case -1:;
411 in_device_name = tmp; 349 }
412 } 350
413 351 { /* Check files */
414 printf("Input device: %s\n", in_device_name); 352 if (!af_name) {
415 } 353 printf("Required audio input file!\n");
416 354 exit(1);
417 { 355 }
418 long dev = get_device_idx(argv[1]); 356
419 if (dev == -1) 357 if (!vf_name) {
420 out_device_name = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); 358 printf("Required video input file!\n");
421 else 359 exit(1);
422 { 360 }
423 const char* tmp; 361
424 i = -1; 362 /* Check for files */
425 for(tmp = alcGetString(NULL, ALC_DEVICE_SPECIFIER); *tmp && i != dev; 363 if(stat(af_name, &st) != 0 || !S_ISREG(st.st_mode))
426 tmp += strlen( tmp ) + 1, ++i) 364 {
427 out_device_name = tmp; 365 printf("%s doesn't seem to be a regular file!\n", af_name);
428 } 366 exit(1);
429 367 }
430 printf("Output device: %s\n", out_device_name); 368
431 } 369 if(stat(vf_name, &st) != 0 || !S_ISREG(st.st_mode))
432 370 {
433 ALCdevice* out_device; 371 printf("%s doesn't seem to be a regular file!\n", vf_name);
434 ALCcontext* out_ctx; 372 exit(1);
435 uint32_t source; 373 }
436 uint32_t buffers[5]; 374 }
375
376 ALCdevice* audio_out_device;
437 377
438 { /* Open output device */ 378 { /* Open output device */
439 out_device = alcOpenDevice(out_device_name); 379 const char* audio_out_dev_name = NULL;
440 if ( !out_device ) { 380
441 fprintf(stderr, "Failed to open playback device: %s: %d\n", out_device_name, alGetError()); 381 int i = 0;
442 return 1; 382 for(audio_out_dev_name = alcGetString(NULL, ALC_DEVICE_SPECIFIER); i < audio_out_dev_idx;
383 audio_out_dev_name += strlen( audio_out_dev_name ) + 1, ++i)
384 if (!(audio_out_dev_name + strlen( audio_out_dev_name ) + 1))
385 break;
386
387 audio_out_device = alcOpenDevice(audio_out_dev_name);
388 if ( !audio_out_device ) {
389 printf("Failed to open playback device: %s: %d\n", audio_out_dev_name, alGetError());
390 exit(1);
443 } 391 }
444 392
445 out_ctx = alcCreateContext(out_device, NULL); 393 ALCcontext* out_ctx = alcCreateContext(audio_out_device, NULL);
446 alcMakeContextCurrent(out_ctx); 394 alcMakeContextCurrent(out_ctx);
447 395
396 uint32_t buffers[5];
448 alGenBuffers(5, buffers); 397 alGenBuffers(5, buffers);
449 alGenSources((uint32_t)1, &source); 398 alGenSources((uint32_t)1, &adout);
450 alSourcei(source, AL_LOOPING, AL_FALSE); 399 alSourcei(adout, AL_LOOPING, AL_FALSE);
451 400
452 uint16_t zeros[10000]; 401 uint16_t zeros[10000];
453 memset(zeros, 0, 10000); 402 memset(zeros, 0, 10000);
@@ -455,45 +404,31 @@ AGAIN:
455 for ( i = 0; i < 5; ++i ) 404 for ( i = 0; i < 5; ++i )
456 alBufferData(buffers[i], AL_FORMAT_STEREO16, zeros, 10000, 48000); 405 alBufferData(buffers[i], AL_FORMAT_STEREO16, zeros, 10000, 48000);
457 406
458 alSourceQueueBuffers(source, 5, buffers); 407 alSourceQueueBuffers(adout, 5, buffers);
459 alSourcePlay(source); 408 alSourcePlay(adout);
409
410 printf("Using audio device: %s\n", audio_out_dev_name);
460 } 411 }
461 412
462 ALCdevice* in_device; 413 printf("Using audio file: %s\n", af_name);
463 414 printf("Using video file: %s\n", vf_name);
464 { /* Open input device */ 415
465 in_device = alcCaptureOpenDevice(in_device_name, 48000, AL_FORMAT_STEREO16, 10000);
466 if ( !in_device ) {
467 fprintf(stderr, "Failed to open capture device: %s: %d\n", in_device_name, alGetError());
468 return 1;
469 }
470
471 alcCaptureStart(in_device);
472 }
473 416
474 Tox *Bsn = tox_new(0);
475 Tox *Alice = tox_new(0);
476 Tox *Bob = tox_new(0);
477 417
478 assert(Bsn && Alice && Bob);
479 418
480 prepare(Bsn, Alice, Bob);
481 419
420 /* START TOX NETWORK */
421
422 Tox *bootstrap;
423 ToxAV *AliceAV;
424 ToxAV *BobAV;
425
426 CallControl AliceCC;
427 CallControl BobCC;
428
429 initialize_tox(&bootstrap, &AliceAV, &AliceCC, &BobAV, &BobCC);
482 430
483 ToxAV *AliceAV, *BobAV;
484 CallControl AliceCC, BobCC;
485 431
486 {
487 TOXAV_ERR_NEW rc;
488 AliceAV = toxav_new(Alice, &rc);
489 assert(rc == TOXAV_ERR_NEW_OK);
490
491 BobAV = toxav_new(Bob, &rc);
492 assert(rc == TOXAV_ERR_NEW_OK);
493
494 prepareAV(AliceAV, &AliceCC, BobAV, &BobCC);
495 printf("Created 2 instances of ToxAV\n");
496 }
497 432
498 433
499#define REGULAR_CALL_FLOW(A_BR, V_BR) \ 434#define REGULAR_CALL_FLOW(A_BR, V_BR) \
@@ -539,7 +474,7 @@ AGAIN:
539 } \ 474 } \
540 } \ 475 } \
541 \ 476 \
542 iterate(Bsn, AliceAV, BobAV); \ 477 iterate(bootstrap, AliceAV, BobAV); \
543 } \ 478 } \
544 printf("Success!\n");\ 479 printf("Success!\n");\
545 } while(0) 480 } while(0)
@@ -578,7 +513,7 @@ AGAIN:
578 } 513 }
579 514
580 while (!BobCC.incoming) 515 while (!BobCC.incoming)
581 iterate(Bsn, AliceAV, BobAV); 516 iterate_tox(bootstrap, AliceAV, BobAV);
582 517
583 /* Reject */ 518 /* Reject */
584 { 519 {
@@ -592,7 +527,7 @@ AGAIN:
592 } 527 }
593 528
594 while (AliceCC.state != TOXAV_CALL_STATE_END) 529 while (AliceCC.state != TOXAV_CALL_STATE_END)
595 iterate(Bsn, AliceAV, BobAV); 530 iterate_tox(bootstrap, AliceAV, BobAV);
596 531
597 printf("Success!\n"); 532 printf("Success!\n");
598 } 533 }
@@ -614,7 +549,7 @@ AGAIN:
614 } 549 }
615 550
616 while (!BobCC.incoming) 551 while (!BobCC.incoming)
617 iterate(Bsn, AliceAV, BobAV); 552 iterate_tox(bootstrap, AliceAV, BobAV);
618 553
619 /* Cancel */ 554 /* Cancel */
620 { 555 {
@@ -629,7 +564,7 @@ AGAIN:
629 564
630 /* Alice will not receive end state */ 565 /* Alice will not receive end state */
631 while (BobCC.state != TOXAV_CALL_STATE_END) 566 while (BobCC.state != TOXAV_CALL_STATE_END)
632 iterate(Bsn, AliceAV, BobAV); 567 iterate_tox(bootstrap, AliceAV, BobAV);
633 568
634 printf("Success!\n"); 569 printf("Success!\n");
635 } 570 }
@@ -652,7 +587,7 @@ AGAIN:
652 } 587 }
653 588
654 while (!BobCC.incoming) 589 while (!BobCC.incoming)
655 iterate(Bsn, AliceAV, BobAV); 590 iterate_tox(bootstrap, AliceAV, BobAV);
656 591
657 /* At first try all stuff while in invalid state */ 592 /* At first try all stuff while in invalid state */
658 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); 593 assert(!toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
@@ -670,39 +605,39 @@ AGAIN:
670 } 605 }
671 } 606 }
672 607
673 iterate(Bsn, AliceAV, BobAV); 608 iterate_tox(bootstrap, AliceAV, BobAV);
674 609
675 /* Pause and Resume */ 610 /* Pause and Resume */
676 printf("Pause and Resume\n"); 611 printf("Pause and Resume\n");
677 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL)); 612 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_PAUSE, NULL));
678 iterate(Bsn, AliceAV, BobAV); 613 iterate_tox(bootstrap, AliceAV, BobAV);
679 assert(BobCC.state == TOXAV_CALL_STATE_PAUSED); 614 assert(BobCC.state == TOXAV_CALL_STATE_PAUSED);
680 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL)); 615 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_RESUME, NULL));
681 iterate(Bsn, AliceAV, BobAV); 616 iterate_tox(bootstrap, AliceAV, BobAV);
682 assert(BobCC.state & (TOXAV_CALL_STATE_SENDING_A | TOXAV_CALL_STATE_SENDING_V)); 617 assert(BobCC.state & (TOXAV_CALL_STATE_SENDING_A | TOXAV_CALL_STATE_SENDING_V));
683 618
684 /* Mute/Unmute single */ 619 /* Mute/Unmute single */
685 printf("Mute/Unmute single\n"); 620 printf("Mute/Unmute single\n");
686 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 621 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
687 iterate(Bsn, AliceAV, BobAV); 622 iterate_tox(bootstrap, AliceAV, BobAV);
688 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A); 623 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
689 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 624 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
690 iterate(Bsn, AliceAV, BobAV); 625 iterate_tox(bootstrap, AliceAV, BobAV);
691 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A); 626 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
692 627
693 /* Mute/Unmute both */ 628 /* Mute/Unmute both */
694 printf("Mute/Unmute both\n"); 629 printf("Mute/Unmute both\n");
695 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 630 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
696 iterate(Bsn, AliceAV, BobAV); 631 iterate_tox(bootstrap, AliceAV, BobAV);
697 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A); 632 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_A);
698 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL)); 633 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL));
699 iterate(Bsn, AliceAV, BobAV); 634 iterate_tox(bootstrap, AliceAV, BobAV);
700 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_V); 635 assert(BobCC.state ^ TOXAV_CALL_STATE_RECEIVING_V);
701 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL)); 636 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, NULL));
702 iterate(Bsn, AliceAV, BobAV); 637 iterate_tox(bootstrap, AliceAV, BobAV);
703 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A); 638 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_A);
704 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL)); 639 assert(toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_TOGGLE_MUTE_VIDEO, NULL));
705 iterate(Bsn, AliceAV, BobAV); 640 iterate_tox(bootstrap, AliceAV, BobAV);
706 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_V); 641 assert(BobCC.state & TOXAV_CALL_STATE_RECEIVING_V);
707 642
708 { 643 {
@@ -715,21 +650,22 @@ AGAIN:
715 } 650 }
716 } 651 }
717 652
718 iterate(Bsn, AliceAV, BobAV); 653 iterate_tox(bootstrap, AliceAV, BobAV);
719 assert(BobCC.state == TOXAV_CALL_STATE_END); 654 assert(BobCC.state == TOXAV_CALL_STATE_END);
720 655
721 printf("Success!\n"); 656 printf("Success!\n");
722 } 657 }
723 658
724 if (TEST_TRANSFER_A) { /* Audio encoding/decoding and transfer */ 659 if (TEST_TRANSFER_A) { /* Audio encoding/decoding and transfer */
660 SNDFILE* af_handle;
661 SF_INFO af_info;
662
725 printf("\nTrying audio enc/dec...\n"); 663 printf("\nTrying audio enc/dec...\n");
726 664
727 memset(&AliceCC, 0, sizeof(CallControl)); 665 memset(&AliceCC, 0, sizeof(CallControl));
728 memset(&BobCC, 0, sizeof(CallControl)); 666 memset(&BobCC, 0, sizeof(CallControl));
729
730 AliceCC.output_source = BobCC.output_source = source;
731 667
732 { 668 { /* Call */
733 TOXAV_ERR_CALL rc; 669 TOXAV_ERR_CALL rc;
734 toxav_call(AliceAV, 0, 48, 0, &rc); 670 toxav_call(AliceAV, 0, 48, 0, &rc);
735 671
@@ -740,11 +676,11 @@ AGAIN:
740 } 676 }
741 677
742 while (!BobCC.incoming) 678 while (!BobCC.incoming)
743 iterate(Bsn, AliceAV, BobAV); 679 iterate_tox(bootstrap, AliceAV, BobAV);
744 680
745 { 681 { /* Answer */
746 TOXAV_ERR_ANSWER rc; 682 TOXAV_ERR_ANSWER rc;
747 toxav_answer(BobAV, 0, 48, 0, &rc); 683 toxav_answer(BobAV, 0, 64, 0, &rc);
748 684
749 if (rc != TOXAV_ERR_ANSWER_OK) { 685 if (rc != TOXAV_ERR_ANSWER_OK) {
750 printf("toxav_answer failed: %d\n", rc); 686 printf("toxav_answer failed: %d\n", rc);
@@ -752,26 +688,44 @@ AGAIN:
752 } 688 }
753 } 689 }
754 690
755 iterate(Bsn, AliceAV, BobAV); 691 iterate_tox(bootstrap, AliceAV, BobAV);
756
757 int16_t PCM[10000];
758 time_t start_time = time(NULL);
759 692
693 /* Open audio file */
694 af_handle = sf_open(af_name, SFM_READ, &af_info);
695 if (af_handle == NULL)
696 {
697 printf("Failed to open the file.\n");
698 exit(1);
699 }
700
760 /* Run for 5 seconds */ 701 /* Run for 5 seconds */
761 while ( start_time + 10 > time(NULL) ) { 702
762 int frame_size = device_read_frame(in_device, 20, PCM, sizeof(PCM)); 703 uint32_t frame_duration = 10;
763 if (frame_size > 0) { 704 int16_t PCM[10000];
764 TOXAV_ERR_SEND_FRAME rc; 705
765 if (toxav_send_audio_frame(AliceAV, 0, PCM, frame_size, 2, 8000, &rc) == false) { 706 time_t start_time = time(NULL);
766 printf("Error sending frame of size %d: %d\n", frame_size, rc); 707 time_t expected_time = af_info.frames / af_info.samplerate + 2;
767 exit (1); 708
768 } 709 while ( start_time + expected_time > time(NULL) ) {
769 } 710 int frame_size = (af_info.samplerate * frame_duration / 1000);
770 711
771 iterate(Bsn, AliceAV, BobAV); 712 int64_t count = sf_read_short(af_handle, PCM, frame_size);
713 if (count > 0) {
714 TOXAV_ERR_SEND_FRAME rc;
715 if (toxav_send_audio_frame(AliceAV, 0, PCM, count, af_info.channels, af_info.samplerate, &rc) == false) {
716 printf("Error sending frame of size %ld: %d\n", count, rc);
717 exit(1);
718 }
719 }
720
721 iterate_tox(bootstrap, AliceAV, BobAV);
772 } 722 }
723
724 printf("Played file in: %lu\n", time(NULL) - start_time);
725
726 sf_close(af_handle);
773 727
774 { 728 { /* Hangup */
775 TOXAV_ERR_CALL_CONTROL rc; 729 TOXAV_ERR_CALL_CONTROL rc;
776 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc); 730 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
777 731
@@ -781,24 +735,19 @@ AGAIN:
781 } 735 }
782 } 736 }
783 737
784 iterate(Bsn, AliceAV, BobAV); 738 iterate_tox(bootstrap, AliceAV, BobAV);
785 assert(BobCC.state == TOXAV_CALL_STATE_END); 739 assert(BobCC.state == TOXAV_CALL_STATE_END);
786 740
787 printf("Success!"); 741 printf("Success!");
788 } 742 }
789 743
790 if (TEST_TRANSFER_V) { 744 if (TEST_TRANSFER_V) {
791 if (strlen(video_in) == 0) { 745 cvNamedWindow(vdout, CV_WINDOW_AUTOSIZE);
792 printf("Skipping video test...\n");
793 goto CONTINUE;
794 }
795 746
796 cvNamedWindow(video_test_window, CV_WINDOW_AUTOSIZE); 747 CvCapture* capture = cvCreateFileCapture(vf_name);
797
798 CvCapture* capture = cvCreateFileCapture(video_in);
799 if (!capture) { 748 if (!capture) {
800 printf("No file named: %s\n", video_in); 749 printf("Failed to open video file: %s\n", vf_name);
801 return 1; 750 exit(1);
802 } 751 }
803 752
804 IplImage* frame; 753 IplImage* frame;
@@ -812,21 +761,20 @@ AGAIN:
812 } 761 }
813 762
814 cvReleaseCapture(&capture); 763 cvReleaseCapture(&capture);
815 cvDestroyWindow(video_test_window); 764 cvDestroyWindow(vdout);
816
817 CONTINUE:;
818 } 765 }
819 766
820 767
768 Tox* Alice = toxav_get_tox(AliceAV);
769 Tox* Bob = toxav_get_tox(BobAV);
821 toxav_kill(BobAV); 770 toxav_kill(BobAV);
822 toxav_kill(AliceAV); 771 toxav_kill(AliceAV);
823 tox_kill(Bob); 772 tox_kill(Bob);
824 tox_kill(Alice); 773 tox_kill(Alice);
825 tox_kill(Bsn); 774 tox_kill(bootstrap);
826 775
827 printf("\nTest successful!\n"); 776 printf("\nTest successful!\n");
828 777
829 alcCloseDevice(out_device); 778 alcCloseDevice(audio_out_device);
830 alcCaptureCloseDevice(in_device);
831 return 0; 779 return 0;
832} 780}
diff --git a/toxav/codec.c b/toxav/codec.c
index a72b2764..b9cbbc06 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -38,7 +38,7 @@
38#include "rtp.h" 38#include "rtp.h"
39#include "codec.h" 39#include "codec.h"
40 40
41#define DEFAULT_JBUF 6 41#define DEFAULT_JBUF 3
42 42
43/* Good quality encode. */ 43/* Good quality encode. */
44#define MAX_DECODE_TIME_US 0 44#define MAX_DECODE_TIME_US 0
@@ -175,6 +175,8 @@ static int jbuf_write(JitterBuffer *q, RTPMessage *m)
175 unsigned int num = sequnum % q->size; 175 unsigned int num = sequnum % q->size;
176 176
177 if ((uint32_t)(sequnum - q->bottom) > q->size) { 177 if ((uint32_t)(sequnum - q->bottom) > q->size) {
178 LOGGER_DEBUG("Clearing jitter: %p", q);
179
178 jbuf_clear(q); 180 jbuf_clear(q);
179 q->bottom = sequnum - q->capacity; 181 q->bottom = sequnum - q->capacity;
180 q->queue[num] = m; 182 q->queue[num] = m;
@@ -193,7 +195,7 @@ static int jbuf_write(JitterBuffer *q, RTPMessage *m)
193 return 0; 195 return 0;
194} 196}
195 197
196/* Success is 0 when there is nothing to dequeue, 198/* success is set to 0 when there is nothing to dequeue,
197 * 1 when there's a good packet, 199 * 1 when there's a good packet,
198 * 2 when there's a lost packet */ 200 * 2 when there's a lost packet */
199static RTPMessage *jbuf_read(JitterBuffer *q, int32_t *success) 201static RTPMessage *jbuf_read(JitterBuffer *q, int32_t *success)
@@ -237,62 +239,6 @@ static int convert_bw_to_sampling_rate(int bw)
237} 239}
238 240
239 241
240int cs_set_receiving_audio_bitrate(CSSession *cs, int32_t rate)
241{
242 if (cs->audio_decoder == NULL)
243 return -1;
244
245 int rc = opus_decoder_ctl(cs->audio_decoder, OPUS_SET_BITRATE(rate));
246
247 if ( rc != OPUS_OK ) {
248 LOGGER_ERROR("Error while setting decoder ctl: %s", opus_strerror(rc));
249 return -1;
250 }
251
252 LOGGER_DEBUG("Set new decoder bitrate to: %d", rate);
253 return 0;
254}
255
256int cs_set_receiving_audio_sampling_rate(CSSession* cs, int32_t rate)
257{
258 /* TODO Find a better way? */
259 if (cs->audio_decoder == NULL)
260 return -1;
261
262 if (cs->decoder_sample_rate == rate)
263 return 0;
264
265 int channels = cs->decoder_channels;
266
267 cs_disable_audio_receiving(cs);
268
269 cs->decoder_sample_rate = rate;
270 cs->decoder_channels = channels;
271
272 LOGGER_DEBUG("Set new encoder sampling rate: %d", rate);
273 return cs_enable_audio_receiving(cs);
274}
275
276int cs_set_receiving_audio_channels(CSSession* cs, int32_t count)
277{
278 /* TODO Find a better way? */
279 if (cs->audio_decoder == NULL)
280 return -1;
281
282 if (cs->decoder_channels == count)
283 return 0;
284
285 int srate = cs->decoder_sample_rate;
286 cs_disable_audio_receiving(cs);
287
288 cs->decoder_channels = count;
289 cs->decoder_sample_rate = srate;
290
291 LOGGER_DEBUG("Set new encoder channel count: %d", count);
292 return cs_enable_audio_receiving(cs);
293}
294
295
296/* PUBLIC */ 242/* PUBLIC */
297 243
298void cs_do(CSSession *cs) 244void cs_do(CSSession *cs)
@@ -310,17 +256,19 @@ void cs_do(CSSession *cs)
310 256
311 pthread_mutex_lock(cs->queue_mutex); 257 pthread_mutex_lock(cs->queue_mutex);
312 258
259 /********************* AUDIO *********************/
313 if (cs->audio_decoder) { /* If receiving enabled */ 260 if (cs->audio_decoder) { /* If receiving enabled */
314 RTPMessage *msg; 261 RTPMessage *msg;
315 262
316 uint16_t fsize = 10000; /* Should be enough for all normal frequences */ 263 /* The maximum for 120 ms 48 KHz audio */
317 int16_t tmp[fsize * 2]; 264 int16_t tmp[20000];
318 265
319 while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) { 266 while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) {
320 pthread_mutex_unlock(cs->queue_mutex); 267 pthread_mutex_unlock(cs->queue_mutex);
321 268
322 if (success == 2) { 269 if (success == 2) {
323 rc = opus_decode(cs->audio_decoder, 0, 0, tmp, fsize, 1); 270 rc = opus_decode(cs->audio_decoder, NULL, 0, tmp,
271 cs->last_packet_sampling_rate * cs->last_packet_frame_duration / 1000, 1);
324 } else { 272 } else {
325 /* Get values from packet and decode. 273 /* Get values from packet and decode.
326 * It also checks for validity of an opus packet 274 * It also checks for validity of an opus packet
@@ -328,7 +276,7 @@ void cs_do(CSSession *cs)
328 rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data)); 276 rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data));
329 if (rc != -1) { 277 if (rc != -1) {
330 cs->last_packet_sampling_rate = rc; 278 cs->last_packet_sampling_rate = rc;
331 cs->last_pack_channels = opus_packet_get_nb_channels(msg->data); 279 cs->last_packet_channels = opus_packet_get_nb_channels(msg->data);
332 280
333 cs->last_packet_frame_duration = 281 cs->last_packet_frame_duration =
334 ( opus_packet_get_samples_per_frame(msg->data, cs->last_packet_sampling_rate) * 1000 ) 282 ( opus_packet_get_samples_per_frame(msg->data, cs->last_packet_sampling_rate) * 1000 )
@@ -339,11 +287,7 @@ void cs_do(CSSession *cs)
339 continue; 287 continue;
340 } 288 }
341 289
342 cs_set_receiving_audio_sampling_rate(cs, cs->last_packet_sampling_rate); 290 rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, sizeof(tmp), 0);
343 cs_set_receiving_audio_channels(cs, cs->last_pack_channels);
344
345 LOGGER_DEBUG("Decoding packet of length: %d", msg->length);
346 rc = opus_decode(cs->audio_decoder, msg->data, msg->length, tmp, fsize, 0);
347 rtp_free_msg(NULL, msg); 291 rtp_free_msg(NULL, msg);
348 } 292 }
349 293
@@ -351,15 +295,28 @@ void cs_do(CSSession *cs)
351 LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); 295 LOGGER_WARNING("Decoding error: %s", opus_strerror(rc));
352 } else if (cs->acb.first) { 296 } else if (cs->acb.first) {
353 /* Play */ 297 /* Play */
354 LOGGER_DEBUG("Playing audio frame size: %d chans: %d srate: %d", rc, cs->last_pack_channels, cs->last_packet_sampling_rate); 298
299 LOGGER_DEBUG("Playing audio frame size: %d; channels: %d; srate: %d; duration %d", rc,
300 cs->last_packet_channels, cs->last_packet_sampling_rate, cs->last_packet_frame_duration);
301
302 /* According to https://tools.ietf.org/html/rfc6716#section-2.1.2
303 * Every encoder can encode both mono and stereo data so we must
304 * determine which format is selected.
305 */
306
307 if (cs->last_packet_channels == 2) {
308 /* The packet is encoded with stereo encoder */
309 }
310
355 cs->acb.first(cs->agent, cs->friend_id, tmp, rc, 311 cs->acb.first(cs->agent, cs->friend_id, tmp, rc,
356 cs->last_pack_channels, cs->last_packet_sampling_rate, cs->acb.second); 312 cs->last_packet_channels, cs->last_packet_sampling_rate, cs->acb.second);
357 } 313 }
358 314
359 pthread_mutex_lock(cs->queue_mutex); 315 pthread_mutex_lock(cs->queue_mutex);
360 } 316 }
361 } 317 }
362 318
319 /********************* VIDEO *********************/
363 if (cs->vbuf_raw && !buffer_empty(cs->vbuf_raw)) { 320 if (cs->vbuf_raw && !buffer_empty(cs->vbuf_raw)) {
364 /* Decode video */ 321 /* Decode video */
365 buffer_read(cs->vbuf_raw, &p); 322 buffer_read(cs->vbuf_raw, &p);
@@ -411,8 +368,6 @@ CSSession *cs_new(uint32_t peer_video_frame_piece_size)
411 368
412 cs->peer_video_frame_piece_size = peer_video_frame_piece_size; 369 cs->peer_video_frame_piece_size = peer_video_frame_piece_size;
413 370
414 cs->decoder_sample_rate = 48000;
415 cs->decoder_channels = 2;
416 return cs; 371 return cs;
417} 372}
418 373
@@ -538,6 +493,8 @@ int cs_set_sending_video_bitrate(CSSession *cs, uint32_t bitrate)
538 return 0; 493 return 0;
539} 494}
540 495
496
497
541int cs_enable_video_sending(CSSession* cs, uint32_t bitrate) 498int cs_enable_video_sending(CSSession* cs, uint32_t bitrate)
542{ 499{
543 if (cs->v_encoding) 500 if (cs->v_encoding)
@@ -619,6 +576,8 @@ FAILURE:
619 return -1; 576 return -1;
620} 577}
621 578
579
580
622void cs_disable_video_sending(CSSession* cs) 581void cs_disable_video_sending(CSSession* cs)
623{ 582{
624 if (cs->v_encoding) { 583 if (cs->v_encoding) {
@@ -663,64 +622,13 @@ int cs_set_sending_audio_bitrate(CSSession *cs, int32_t rate)
663 return 0; 622 return 0;
664} 623}
665 624
666int cs_set_sending_audio_sampling_rate(CSSession* cs, int32_t rate)
667{
668 /* TODO Find a better way? */
669 if (cs->audio_encoder == NULL)
670 return -1;
671
672 if (cs->encoder_sample_rate == rate)
673 return 0;
674
675 int rc = OPUS_OK;
676 int bitrate = 0;
677 int channels = cs->encoder_channels;
678
679 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_BITRATE(&bitrate));
680
681 if ( rc != OPUS_OK ) {
682 LOGGER_ERROR("Error while getting encoder ctl: %s", opus_strerror(rc));
683 return -1;
684 }
685
686 cs_disable_audio_sending(cs);
687 cs->encoder_sample_rate = rate;
688
689 LOGGER_DEBUG("Set new encoder sampling rate: %d", rate);
690 return cs_enable_audio_sending(cs, bitrate, channels);
691}
692 625
693int cs_set_sending_audio_channels(CSSession* cs, int32_t count)
694{
695 /* TODO Find a better way? */
696 if (cs->audio_encoder == NULL)
697 return -1;
698
699 if (cs->encoder_channels == count)
700 return 0;
701
702 int rc = OPUS_OK;
703 int bitrate = 0;
704
705 rc = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_BITRATE(&bitrate));
706
707 if ( rc != OPUS_OK ) {
708 LOGGER_ERROR("Error while getting encoder ctl: %s", opus_strerror(rc));
709 return -1;
710 }
711
712 cs_disable_audio_sending(cs);
713
714 LOGGER_DEBUG("Set new encoder channel count: %d", count);
715 return cs_enable_audio_sending(cs, bitrate, count);
716}
717 626
718void cs_disable_audio_sending(CSSession* cs) 627void cs_disable_audio_sending(CSSession* cs)
719{ 628{
720 if ( cs->audio_encoder ) { 629 if ( cs->audio_encoder ) {
721 opus_encoder_destroy(cs->audio_encoder); 630 opus_encoder_destroy(cs->audio_encoder);
722 cs->audio_encoder = NULL; 631 cs->audio_encoder = NULL;
723 cs->encoder_channels = 0;
724 } 632 }
725} 633}
726 634
@@ -732,26 +640,22 @@ void cs_disable_audio_receiving(CSSession* cs)
732 jbuf_free(cs->j_buf); 640 jbuf_free(cs->j_buf);
733 cs->j_buf = NULL; 641 cs->j_buf = NULL;
734 642
735 /* It's used for measuring iteration interval so this has to be some value. 643 /* These need to be set in order to properly
736 * To avoid unecessary checking we set this to 500 644 * do error correction with opus */
737 */ 645 cs->last_packet_frame_duration = 120;
738 cs->last_packet_frame_duration = 500; 646 cs->last_packet_sampling_rate = 48000;
739 cs->decoder_sample_rate = 48000;
740 cs->decoder_channels = 2;
741 } 647 }
742} 648}
743 649
744int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate, int channels) 650
651
652int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate)
745{ 653{
746 if (cs->audio_encoder) 654 if (cs->audio_encoder)
747 return 0; 655 return 0;
748 656
749 if (!cs->encoder_sample_rate)
750 cs->encoder_sample_rate = 48000;
751 cs->encoder_channels = channels;
752
753 int rc = OPUS_OK; 657 int rc = OPUS_OK;
754 cs->audio_encoder = opus_encoder_create(cs->encoder_sample_rate, channels, OPUS_APPLICATION_AUDIO, &rc); 658 cs->audio_encoder = opus_encoder_create(48000, 2, OPUS_APPLICATION_AUDIO, &rc);
755 659
756 if ( rc != OPUS_OK ) { 660 if ( rc != OPUS_OK ) {
757 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc)); 661 LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc));
@@ -785,7 +689,7 @@ int cs_enable_audio_receiving(CSSession* cs)
785 return 0; 689 return 0;
786 690
787 int rc; 691 int rc;
788 cs->audio_decoder = opus_decoder_create(cs->decoder_sample_rate, cs->decoder_channels, &rc ); 692 cs->audio_decoder = opus_decoder_create(48000, 2, &rc );
789 693
790 if ( rc != OPUS_OK ) { 694 if ( rc != OPUS_OK ) {
791 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc)); 695 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc));
@@ -800,10 +704,11 @@ int cs_enable_audio_receiving(CSSession* cs)
800 return -1; 704 return -1;
801 } 705 }
802 706
803 /* It's used for measuring iteration interval so this has to be some value. 707
804 * To avoid unecessary checking we set this to 500 708 /* These need to be set in order to properly
805 */ 709 * do error correction with opus */
806 cs->last_packet_frame_duration = 500; 710 cs->last_packet_frame_duration = 120;
711 cs->last_packet_sampling_rate = 48000;
807 712
808 return 0; 713 return 0;
809} 714}
@@ -813,8 +718,8 @@ int cs_enable_audio_receiving(CSSession* cs)
813/* Called from RTP */ 718/* Called from RTP */
814void queue_message(RTPSession *session, RTPMessage *msg) 719void queue_message(RTPSession *session, RTPMessage *msg)
815{ 720{
816 /* This function is unregistered during call termination befor destroing 721 /* This function is unregistered during call termination befor destroying
817 * Codec session so no need to check for validity of cs 722 * Codec session so no need to check for validity of cs TODO properly check video cycle
818 */ 723 */
819 CSSession *cs = session->cs; 724 CSSession *cs = session->cs;
820 725
diff --git a/toxav/codec.h b/toxav/codec.h
index 5e015f39..526a80d5 100644
--- a/toxav/codec.h
+++ b/toxav/codec.h
@@ -107,25 +107,15 @@ typedef struct CSSession_s {
107 107
108 /* audio encoding */ 108 /* audio encoding */
109 OpusEncoder *audio_encoder; 109 OpusEncoder *audio_encoder;
110 int32_t encoder_channels;
111 int32_t encoder_sample_rate;
112 110
113 /* audio decoding */ 111 /* audio decoding */
114 OpusDecoder *audio_decoder; 112 OpusDecoder *audio_decoder;
115 int32_t decoder_channels; 113 int32_t last_packet_channels;
116 int32_t decoder_sample_rate;
117 int32_t last_pack_channels;
118 int32_t last_packet_sampling_rate; 114 int32_t last_packet_sampling_rate;
119 int32_t last_packet_frame_duration; 115 int32_t last_packet_frame_duration;
120 struct JitterBuffer_s *j_buf; 116 struct JitterBuffer_s *j_buf;
121 117
122 118
123 /* Voice activity detection */
124 uint32_t EVAD_tolerance; /* In frames */
125 uint32_t EVAD_tolerance_cr;
126
127
128
129 /* OTHER 119 /* OTHER
130 * 120 *
131 * 121 *
@@ -171,10 +161,8 @@ void cs_disable_video_receiving(CSSession* cs);
171 * AUDIO HANDLING 161 * AUDIO HANDLING
172 */ 162 */
173int cs_set_sending_audio_bitrate(CSSession* cs, int32_t rate); 163int cs_set_sending_audio_bitrate(CSSession* cs, int32_t rate);
174int cs_set_sending_audio_sampling_rate(CSSession* cs, int32_t rate);
175int cs_set_sending_audio_channels(CSSession* cs, int32_t count);
176 164
177int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate, int channels); 165int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate);
178int cs_enable_audio_receiving(CSSession* cs); 166int cs_enable_audio_receiving(CSSession* cs);
179 167
180void cs_disable_audio_sending(CSSession* cs); 168void cs_disable_audio_sending(CSSession* cs);
diff --git a/toxav/toxav.c b/toxav/toxav.c
index fcc6e86a..84a0c43a 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -208,7 +208,7 @@ void toxav_iterate(ToxAV* av)
208 return; 208 return;
209 209
210 uint64_t start = current_time_monotonic(); 210 uint64_t start = current_time_monotonic();
211 uint32_t rc = 0; 211 uint32_t rc = 500;
212 212
213 pthread_mutex_lock(av->mutex); 213 pthread_mutex_lock(av->mutex);
214 ToxAVCall* i = av->calls[av->calls_head]; 214 ToxAVCall* i = av->calls[av->calls_head];
@@ -225,7 +225,7 @@ void toxav_iterate(ToxAV* av)
225 pthread_mutex_lock(av->mutex); 225 pthread_mutex_lock(av->mutex);
226 } 226 }
227 227
228 av->interval = rc < av->dmssa ? 0 : rc - av->dmssa; 228 av->interval = rc < av->dmssa ? 0 : (rc - av->dmssa);
229 av->dmsst += current_time_monotonic() - start; 229 av->dmsst += current_time_monotonic() - start;
230 230
231 if (++av->dmssc == 3) { 231 if (++av->dmssc == 3) {
@@ -650,9 +650,6 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
650 } 650 }
651 651
652 { /* Encode and send */ 652 { /* Encode and send */
653 cs_set_sending_audio_channels(call->cs, channels);
654 cs_set_sending_audio_sampling_rate(call->cs, sampling_rate);
655
656 uint8_t dest[sample_count * channels * 2 /* sizeof(uint16_t) */]; 653 uint8_t dest[sample_count * channels * 2 /* sizeof(uint16_t) */];
657 int vrc = opus_encode(call->cs->audio_encoder, pcm, sample_count, dest, sizeof (dest)); 654 int vrc = opus_encode(call->cs->audio_encoder, pcm, sample_count, dest, sizeof (dest));
658 655
@@ -667,8 +664,6 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
667 LOGGER_WARNING("Failed to send audio packet"); 664 LOGGER_WARNING("Failed to send audio packet");
668 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED; 665 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
669 } 666 }
670
671 LOGGER_DEBUG("Sent packet of size: %d (o %d)", vrc, sample_count);
672 } 667 }
673 668
674 pthread_mutex_unlock(call->mutex_audio_sending); 669 pthread_mutex_unlock(call->mutex_audio_sending);
@@ -956,7 +951,7 @@ bool call_prepare_transmission(ToxAVCall* call)
956 call->rtps[audio_index]->cs = call->cs; 951 call->rtps[audio_index]->cs = call->cs;
957 952
958 /* Only enable sending if bitrate is defined */ 953 /* Only enable sending if bitrate is defined */
959 if (call->s_audio_b > 0 && cs_enable_audio_sending(call->cs, call->s_audio_b * 1000, 2) != 0) { 954 if (call->s_audio_b > 0 && cs_enable_audio_sending(call->cs, call->s_audio_b * 1000) != 0) {
960 LOGGER_WARNING("Failed to enable audio sending!"); 955 LOGGER_WARNING("Failed to enable audio sending!");
961 goto FAILURE; 956 goto FAILURE;
962 } 957 }