diff options
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/Makefile.inc | 1 | ||||
-rw-r--r-- | toxav/av_test.c | 602 | ||||
-rw-r--r-- | toxav/codec.c | 187 | ||||
-rw-r--r-- | toxav/codec.h | 16 | ||||
-rw-r--r-- | toxav/toxav.c | 11 |
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 | ||
46 | typedef struct { | 43 | typedef 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 | ||
52 | const char* video_test_window = "AV Test"; | 48 | const char* vdout = "AV Test"; |
49 | uint32_t adout; | ||
53 | 50 | ||
54 | const char* stringify_state(TOXAV_CALL_STATE s) | 51 | const 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 | |||
71 | int 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 | } |
123 | void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, | 119 | void 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 | } |
132 | void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) | 153 | void 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 | */ |
142 | void prepare(Tox* Bsn, Tox* Alice, Tox* Bob) | 163 | void 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; |
174 | void 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 | } |
188 | void iterate(Tox* Bsn, ToxAV* AliceAV, ToxAV* BobAV) | 228 | int 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 | |||
203 | int 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 | |||
220 | int 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 | |||
250 | int 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 | |||
282 | int 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 | |||
288 | long 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 | ||
304 | int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img) | 246 | int 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 | ||
344 | int main (int argc, char** argv) | 288 | int 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 | ||
351 | AGAIN: | 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 | |||
304 | int 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 | |||
316 | int 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 */ |
199 | static RTPMessage *jbuf_read(JitterBuffer *q, int32_t *success) | 201 | static 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 | ||
240 | int 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 | |||
256 | int 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 | |||
276 | int 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 | ||
298 | void cs_do(CSSession *cs) | 244 | void 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 | |||
541 | int cs_enable_video_sending(CSSession* cs, uint32_t bitrate) | 498 | int 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 | |||
622 | void cs_disable_video_sending(CSSession* cs) | 581 | void 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 | ||
666 | int 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 | ||
693 | int 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 | ||
718 | void cs_disable_audio_sending(CSSession* cs) | 627 | void 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 | ||
744 | int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate, int channels) | 650 | |
651 | |||
652 | int 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 */ |
814 | void queue_message(RTPSession *session, RTPMessage *msg) | 719 | void 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 | */ |
173 | int cs_set_sending_audio_bitrate(CSSession* cs, int32_t rate); | 163 | int cs_set_sending_audio_bitrate(CSSession* cs, int32_t rate); |
174 | int cs_set_sending_audio_sampling_rate(CSSession* cs, int32_t rate); | ||
175 | int cs_set_sending_audio_channels(CSSession* cs, int32_t count); | ||
176 | 164 | ||
177 | int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate, int channels); | 165 | int cs_enable_audio_sending(CSSession* cs, uint32_t bitrate); |
178 | int cs_enable_audio_receiving(CSSession* cs); | 166 | int cs_enable_audio_receiving(CSSession* cs); |
179 | 167 | ||
180 | void cs_disable_audio_sending(CSSession* cs); | 168 | void 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 | } |