summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2020-03-02 20:51:25 +0000
committeriphydf <iphydf@users.noreply.github.com>2020-03-02 21:07:55 +0000
commit28baf9632f545b6c85235ddbb982369d9a4207ca (patch)
treef0d8c00103b9e542c084f00721c12610e98d2ce7
parent2dc639a8a4ef0f3c4fc9d4b7c4ebdc79d2d7f702 (diff)
Remove testing/av_test.c.
It's a maintenance burden. Nobody uses this. It depends on an ancient version of opencv that less and less systems actually have.
-rw-r--r--.travis.yml11
-rw-r--r--CMakeLists.txt18
-rw-r--r--INSTALL.md1
-rw-r--r--cmake/Dependencies.cmake5
-rw-r--r--testing/av_test.c840
5 files changed, 0 insertions, 875 deletions
diff --git a/.travis.yml b/.travis.yml
index 9bc8ad7f..1328e488 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,14 +16,9 @@ matrix:
16 apt: 16 apt:
17 packages: 17 packages:
18 - libconfig-dev # For tox-bootstrapd. 18 - libconfig-dev # For tox-bootstrapd.
19 - libcv-dev # For av_test.
20 - libhighgui-dev # For av_test.
21 - libopencv-contrib-dev # For av_test.
22 - libopus-dev # For toxav. 19 - libopus-dev # For toxav.
23 - libsndfile1-dev # For av_test.
24 - libgtest-dev # For unit tests. 20 - libgtest-dev # For unit tests.
25 - libvpx-dev # For toxav. 21 - libvpx-dev # For toxav.
26 - portaudio19-dev # For av_test.
27 - pylint 22 - pylint
28 install: .travis/$JOB install 23 install: .travis/$JOB install
29 script: .travis/$JOB script 24 script: .travis/$JOB script
@@ -42,12 +37,6 @@ matrix:
42 - stage: "Stage 1" 37 - stage: "Stage 1"
43 env: JOB=bazel-linux 38 env: JOB=bazel-linux
44 compiler: clang 39 compiler: clang
45 addons:
46 apt:
47 packages:
48 - libcv-dev # For av_test.
49 - libhighgui-dev # For av_test.
50 - libopencv-contrib-dev # For av_test.
51 before_install: 40 before_install:
52 # Clear bazel installation. 41 # Clear bazel installation.
53 - rm -rf $HOME/.cache/bazel/_bazel_$USER/install 42 - rm -rf $HOME/.cache/bazel/_bazel_$USER/install
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7043253e..81a41e7f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -492,24 +492,6 @@ endif()
492# 492#
493################################################################################ 493################################################################################
494 494
495option(BUILD_AV_TEST "Build toxav test" ON)
496if(NOT WIN32
497 AND BUILD_AV_TEST AND BUILD_TOXAV
498 AND SNDFILE_FOUND AND PORTAUDIO_FOUND AND OPENCV_FOUND)
499 add_executable(av_test ${CPUFEATURES}
500 testing/av_test.c)
501 target_link_modules(av_test
502 toxcore
503 ${OPENCV_LIBRARIES}
504 ${PORTAUDIO_LIBRARIES}
505 ${SNDFILE_LIBRARIES})
506 # Due to https://github.com/opencv/opencv/issues/6585, we need to compile
507 # av_test as C++ for newer OpenCV versions.
508 if(NOT OPENCV_VERSION VERSION_LESS 3)
509 set_source_files_properties(testing/av_test.c PROPERTIES LANGUAGE CXX)
510 endif()
511endif()
512
513option(BUILD_MISC_TESTS "Build additional tests" OFF) 495option(BUILD_MISC_TESTS "Build additional tests" OFF)
514if (BUILD_MISC_TESTS) 496if (BUILD_MISC_TESTS)
515 add_executable(DHT_test ${CPUFEATURES} 497 add_executable(DHT_test ${CPUFEATURES}
diff --git a/INSTALL.md b/INSTALL.md
index de6f1095..0e4d19b5 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -85,7 +85,6 @@ There are some options that are available to configure the build.
85|------------------------|-----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------| 85|------------------------|-----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------|
86| `AUTOTEST` | Enable autotests (mainly for CI). | ON or OFF | OFF | 86| `AUTOTEST` | Enable autotests (mainly for CI). | ON or OFF | OFF |
87| `BOOTSTRAP_DAEMON` | Enable building of tox-bootstrapd, the DHT bootstrap node daemon. For Unix-like systems only. | ON or OFF | ON | 87| `BOOTSTRAP_DAEMON` | Enable building of tox-bootstrapd, the DHT bootstrap node daemon. For Unix-like systems only. | ON or OFF | ON |
88| `BUILD_AV_TEST` | Build toxav test. | ON or OFF | ON |
89| `BUILD_MISC_TESTS` | Build additional tests. | ON or OFF | OFF | 88| `BUILD_MISC_TESTS` | Build additional tests. | ON or OFF | OFF |
90| `BUILD_TOXAV` | Whether to build the tox AV library. | ON or OFF | ON | 89| `BUILD_TOXAV` | Whether to build the tox AV library. | ON or OFF | ON |
91| `CMAKE_INSTALL_PREFIX` | Path to where everything should be installed. | Directory path. | Platform-dependent. Refer to CMake documentation. | 90| `CMAKE_INSTALL_PREFIX` | Path to where everything should be installed. | Directory path. | Platform-dependent. Refer to CMake documentation. |
diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake
index 5970fde7..8361e8e1 100644
--- a/cmake/Dependencies.cmake
+++ b/cmake/Dependencies.cmake
@@ -25,11 +25,6 @@ pkg_use_module(LIBCONFIG libconfig )
25# For tox-spectest. 25# For tox-spectest.
26pkg_use_module(MSGPACK msgpack ) 26pkg_use_module(MSGPACK msgpack )
27 27
28# For av_test.
29pkg_use_module(OPENCV opencv )
30pkg_use_module(PORTAUDIO portaudio-2.0)
31pkg_use_module(SNDFILE sndfile )
32
33############################################################################### 28###############################################################################
34# 29#
35# :: For MSVC Windows builds. 30# :: For MSVC Windows builds.
diff --git a/testing/av_test.c b/testing/av_test.c
deleted file mode 100644
index 7dba399b..00000000
--- a/testing/av_test.c
+++ /dev/null
@@ -1,840 +0,0 @@
1/*
2 * Compile with (Linux only; in newly created directory toxcore/dir_name):
3 * gcc -o av_test ../toxav/av_test.c ../build/.libs/libtox*.a -lopencv_core \
4 * -lopencv_highgui -lopencv_imgproc -lsndfile -pthread -lvpx -lopus -lsodium -lportaudio
5 */
6
7/*
8 * Copyright © 2016-2018 The TokTok team.
9 * Copyright © 2013-2015 Tox project.
10 *
11 * This file is part of Tox, the free peer to peer instant messenger.
12 *
13 * Tox is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * Tox is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
25 */
26#define _XOPEN_SOURCE 600
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32// XXX: Hack because toxav doesn't really expose ring_buffer, but this av test
33// uses it. Not all of these functions are used, but when linking statically,
34// not renaming them will cause multiple definition errors, so we need to rename
35// all of them.
36#define RingBuffer TestRingBuffer
37#define rb_full test_rb_full
38#define rb_empty test_rb_empty
39#define rb_write test_rb_write
40#define rb_read test_rb_read
41#define rb_new test_rb_new
42#define rb_kill test_rb_kill
43#define rb_size test_rb_size
44#define rb_data test_rb_data
45#include "../toxav/ring_buffer.c"
46
47#include "../toxav/toxav.h"
48#include "../toxcore/Messenger.h"
49#include "../toxcore/mono_time.h" /* current_time_monotonic() */
50#include "../toxcore/tox.h"
51#include "../toxcore/util.h"
52
53#ifdef __cplusplus
54}
55#endif
56
57/* Playing audio data */
58#include <portaudio.h>
59/* Reading audio */
60#include <sndfile.h>
61
62/* Reading and Displaying video data */
63#include <opencv/cv.h>
64#include <opencv/cvwimage.h>
65#include <opencv/highgui.h>
66#ifdef __APPLE__
67#include <opencv2/videoio/videoio_c.h>
68#endif
69
70#include <assert.h>
71#include <sched.h>
72#include <stdio.h>
73#include <stdlib.h>
74#include <string.h>
75#include <sys/stat.h>
76#include <time.h>
77#include <unistd.h>
78
79#define c_sleep(x) usleep(1000*(x))
80
81
82#define CLIP(X) ((X) > 255 ? 255 : (X) < 0 ? 0 : X)
83
84// RGB -> YUV
85#define RGB2Y(R, G, B) CLIP((( 66 * (R) + 129 * (G) + 25 * (B) + 128) >> 8) + 16)
86#define RGB2U(R, G, B) CLIP(((-38 * (R) - 74 * (G) + 112 * (B) + 128) >> 8) + 128)
87#define RGB2V(R, G, B) CLIP(((112 * (R) - 94 * (G) - 18 * (B) + 128) >> 8) + 128)
88
89// YUV -> RGB
90#define C(Y) ((Y) - 16 )
91#define D(U) ((U) - 128 )
92#define E(V) ((V) - 128 )
93
94#define YUV2R(Y, U, V) CLIP((298 * C(Y) + 409 * E(V) + 128) >> 8)
95#define YUV2G(Y, U, V) CLIP((298 * C(Y) - 100 * D(U) - 208 * E(V) + 128) >> 8)
96#define YUV2B(Y, U, V) CLIP((298 * C(Y) + 516 * D(U) + 128) >> 8)
97
98
99#define TEST_TRANSFER_A 0
100#define TEST_TRANSFER_V 1
101
102
103typedef struct {
104 bool incoming;
105 uint32_t state;
106 pthread_mutex_t arb_mutex[1];
107 RingBuffer *arb; /* Audio ring buffer */
108} CallControl;
109
110struct toxav_thread_data {
111 ToxAV *AliceAV;
112 ToxAV *BobAV;
113 int32_t sig;
114};
115
116static const char *vdout = "AV Test"; /* Video output */
117static PaStream *adout = nullptr; /* Audio output */
118
119typedef struct {
120 uint16_t size;
121 int16_t data[];
122} frame;
123
124static void *pa_write_thread(void *d)
125{
126 /* The purpose of this thread is to make sure Pa_WriteStream will not block
127 * toxav_iterate thread
128 */
129 CallControl *cc = (CallControl *)d;
130
131 while (Pa_IsStreamActive(adout)) {
132 frame *f;
133 pthread_mutex_lock(cc->arb_mutex);
134
135 if (rb_read(cc->arb, (void **)&f)) {
136 pthread_mutex_unlock(cc->arb_mutex);
137 Pa_WriteStream(adout, f->data, f->size);
138 free(f);
139 } else {
140 pthread_mutex_unlock(cc->arb_mutex);
141 c_sleep(10);
142 }
143 }
144
145 return nullptr;
146}
147
148/**
149 * Callbacks
150 */
151static void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data)
152{
153 printf("Handling CALL callback\n");
154 ((CallControl *)user_data)->incoming = true;
155}
156static void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data)
157{
158 printf("Handling CALL STATE callback: %d\n", state);
159 ((CallControl *)user_data)->state = state;
160}
161static void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
162 uint16_t width, uint16_t height,
163 uint8_t const *y, uint8_t const *u, uint8_t const *v,
164 int32_t ystride, int32_t ustride, int32_t vstride,
165 void *user_data)
166{
167 ystride = abs(ystride);
168 ustride = abs(ustride);
169 vstride = abs(vstride);
170
171 uint16_t *img_data = (uint16_t *)malloc(height * width * 6);
172
173 unsigned long int i, j;
174
175 for (i = 0; i < height; ++i) {
176 for (j = 0; j < width; ++j) {
177 uint8_t *point = (uint8_t *) img_data + 3 * ((i * width) + j);
178 int yx = y[(i * ystride) + j];
179 int ux = u[((i / 2) * ustride) + (j / 2)];
180 int vx = v[((i / 2) * vstride) + (j / 2)];
181
182 point[0] = YUV2R(yx, ux, vx);
183 point[1] = YUV2G(yx, ux, vx);
184 point[2] = YUV2B(yx, ux, vx);
185 }
186 }
187
188
189 CvMat mat = cvMat(height, width, CV_8UC3, img_data);
190
191 CvSize sz;
192 sz.height = height;
193 sz.width = width;
194
195 IplImage *header = cvCreateImageHeader(sz, 1, 3);
196 IplImage *img = cvGetImage(&mat, header);
197 cvShowImage(vdout, img);
198 free(img_data);
199}
200static void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
201 int16_t const *pcm,
202 size_t sample_count,
203 uint8_t channels,
204 uint32_t sampling_rate,
205 void *user_data)
206{
207 CallControl *cc = (CallControl *)user_data;
208 frame *f = (frame *)malloc(sizeof(uint16_t) + sample_count * sizeof(int16_t) * channels);
209 memcpy(f->data, pcm, sample_count * sizeof(int16_t) * channels);
210 f->size = sample_count;
211
212 pthread_mutex_lock(cc->arb_mutex);
213 free(rb_write(cc->arb, f));
214 pthread_mutex_unlock(cc->arb_mutex);
215}
216static void t_toxav_audio_bit_rate_cb(ToxAV *av, uint32_t friend_number,
217 uint32_t audio_bit_rate, void *user_data)
218{
219 printf("Suggested bit rate: audio: %u\n", audio_bit_rate);
220}
221static void t_toxav_video_bit_rate_cb(ToxAV *av, uint32_t friend_number,
222 uint32_t video_bit_rate, void *user_data)
223{
224 printf("Suggested bit rate: video: %u\n", video_bit_rate);
225}
226static void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length,
227 void *userdata)
228{
229 if (length == 7 && memcmp("gentoo", data, 7) == 0) {
230 assert(tox_friend_add_norequest(m, public_key, nullptr) != (uint32_t) ~0);
231 }
232}
233
234/**
235 */
236static void initialize_tox(Tox **bootstrap, ToxAV **AliceAV, CallControl *AliceCC, ToxAV **BobAV, CallControl *BobCC)
237{
238 Tox *Alice;
239 Tox *Bob;
240
241 struct Tox_Options *opts = tox_options_new(nullptr);
242 assert(opts != nullptr);
243
244 tox_options_set_end_port(opts, 0);
245 tox_options_set_ipv6_enabled(opts, false);
246
247 {
248 Tox_Err_New error;
249
250 tox_options_set_start_port(opts, 33445);
251 *bootstrap = tox_new(opts, &error);
252 assert(error == TOX_ERR_NEW_OK);
253
254 tox_options_set_start_port(opts, 33455);
255 Alice = tox_new(opts, &error);
256 assert(error == TOX_ERR_NEW_OK);
257
258 tox_options_set_start_port(opts, 33465);
259 Bob = tox_new(opts, &error);
260 assert(error == TOX_ERR_NEW_OK);
261 }
262
263 tox_options_free(opts);
264
265 printf("Created 3 instances of Tox\n");
266 printf("Preparing network...\n");
267 long long unsigned int cur_time = time(nullptr);
268
269 uint32_t to_compare = 974536;
270 uint8_t address[TOX_ADDRESS_SIZE];
271
272 tox_callback_friend_request(Alice, t_accept_friend_request_cb);
273 tox_self_get_address(Alice, address);
274
275
276 assert(tox_friend_add(Bob, address, (const uint8_t *)"gentoo", 7, nullptr) != (uint32_t) ~0);
277
278 uint8_t off = 1;
279
280 while (1) {
281 tox_iterate(*bootstrap, &to_compare);
282 tox_iterate(Alice, &to_compare);
283 tox_iterate(Bob, &to_compare);
284
285 if (tox_self_get_connection_status(*bootstrap) &&
286 tox_self_get_connection_status(Alice) &&
287 tox_self_get_connection_status(Bob) && off) {
288 printf("Toxes are online, took %llu seconds\n", time(nullptr) - cur_time);
289 off = 0;
290 }
291
292 if (tox_friend_get_connection_status(Alice, 0, nullptr) == TOX_CONNECTION_UDP &&
293 tox_friend_get_connection_status(Bob, 0, nullptr) == TOX_CONNECTION_UDP) {
294 break;
295 }
296
297 c_sleep(20);
298 }
299
300
301 Toxav_Err_New rc;
302 *AliceAV = toxav_new(Alice, &rc);
303 assert(rc == TOXAV_ERR_NEW_OK);
304
305 *BobAV = toxav_new(Bob, &rc);
306 assert(rc == TOXAV_ERR_NEW_OK);
307
308
309 /* Alice */
310 toxav_callback_call(*AliceAV, t_toxav_call_cb, AliceCC);
311 toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC);
312 toxav_callback_audio_bit_rate(*AliceAV, t_toxav_audio_bit_rate_cb, AliceCC);
313 toxav_callback_video_bit_rate(*AliceAV, t_toxav_video_bit_rate_cb, AliceCC);
314 toxav_callback_video_receive_frame(*AliceAV, t_toxav_receive_video_frame_cb, AliceCC);
315 toxav_callback_audio_receive_frame(*AliceAV, t_toxav_receive_audio_frame_cb, AliceCC);
316
317 /* Bob */
318 toxav_callback_call(*BobAV, t_toxav_call_cb, BobCC);
319 toxav_callback_call_state(*BobAV, t_toxav_call_state_cb, BobCC);
320 toxav_callback_audio_bit_rate(*BobAV, t_toxav_audio_bit_rate_cb, BobCC);
321 toxav_callback_video_bit_rate(*BobAV, t_toxav_video_bit_rate_cb, BobCC);
322 toxav_callback_video_receive_frame(*BobAV, t_toxav_receive_video_frame_cb, BobCC);
323 toxav_callback_audio_receive_frame(*BobAV, t_toxav_receive_audio_frame_cb, BobCC);
324
325
326 printf("Created 2 instances of ToxAV\n");
327 printf("All set after %llu seconds!\n", time(nullptr) - cur_time);
328}
329static int iterate_tox(Tox *bootstrap, ToxAV *AliceAV, ToxAV *BobAV, void *userdata)
330{
331 tox_iterate(bootstrap, userdata);
332 tox_iterate(toxav_get_tox(AliceAV), userdata);
333 tox_iterate(toxav_get_tox(BobAV), userdata);
334
335 return MIN(tox_iteration_interval(toxav_get_tox(AliceAV)), tox_iteration_interval(toxav_get_tox(BobAV)));
336}
337static void *iterate_toxav(void *data)
338{
339 struct toxav_thread_data *data_cast = (struct toxav_thread_data *)data;
340#if defined TEST_TRANSFER_V && TEST_TRANSFER_V == 1
341 cvNamedWindow(vdout, CV_WINDOW_AUTOSIZE);
342#endif
343
344 while (data_cast->sig == 0) {
345 toxav_iterate(data_cast->AliceAV);
346 toxav_iterate(data_cast->BobAV);
347 int rc = MIN(toxav_iteration_interval(data_cast->AliceAV), toxav_iteration_interval(data_cast->BobAV));
348
349 printf("\rIteration interval: %d ", rc);
350 fflush(stdout);
351
352#if defined TEST_TRANSFER_V && TEST_TRANSFER_V == 1
353
354 if (!rc) {
355 rc = 1;
356 }
357
358 cvWaitKey(rc);
359#else
360 c_sleep(rc);
361#endif
362 }
363
364 data_cast->sig = 1;
365
366#if defined TEST_TRANSFER_V && TEST_TRANSFER_V == 1
367 cvDestroyWindow(vdout);
368#endif
369
370 pthread_exit(nullptr);
371}
372
373static int send_opencv_img(ToxAV *av, uint32_t friend_number, const IplImage *img)
374{
375 int32_t strides[3] = { img->width, img->width / 2, img->width / 2 };
376 uint8_t *planes[3] = {
377 (uint8_t *)malloc(img->height * img->width),
378 (uint8_t *)malloc(img->height * img->width / 4),
379 (uint8_t *)malloc(img->height * img->width / 4),
380 };
381
382 int x_chroma_shift = 1;
383 int y_chroma_shift = 1;
384
385 int x, y;
386
387 for (y = 0; y < img->height; ++y) {
388 for (x = 0; x < img->width; ++x) {
389 uint8_t r = img->imageData[(x + y * img->width) * 3 + 0];
390 uint8_t g = img->imageData[(x + y * img->width) * 3 + 1];
391 uint8_t b = img->imageData[(x + y * img->width) * 3 + 2];
392
393 planes[0][x + y * strides[0]] = RGB2Y(r, g, b);
394
395 if (!(x % (1 << x_chroma_shift)) && !(y % (1 << y_chroma_shift))) {
396 const int i = x / (1 << x_chroma_shift);
397 const int j = y / (1 << y_chroma_shift);
398 planes[1][i + j * strides[1]] = RGB2U(r, g, b);
399 planes[2][i + j * strides[2]] = RGB2V(r, g, b);
400 }
401 }
402 }
403
404 int rc = toxav_video_send_frame(av, friend_number, img->width, img->height,
405 planes[0], planes[1], planes[2], nullptr);
406 free(planes[0]);
407 free(planes[1]);
408 free(planes[2]);
409 return rc;
410}
411static int print_audio_devices(void)
412{
413 int i = 0;
414
415 for (i = 0; i < Pa_GetDeviceCount(); ++i) {
416 const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
417
418 if (info) {
419 printf("%d) %s\n", i, info->name);
420 }
421 }
422
423 return 0;
424}
425static int print_help(const char *name)
426{
427 printf("Usage: %s -[a:v:o:dh]\n"
428 "-a <path> audio input file\n"
429 "-b <ms> audio frame duration\n"
430 "-v <path> video input file\n"
431 "-x <ms> video frame duration\n"
432 "-o <idx> output audio device index\n"
433 "-d print output audio devices\n"
434 "-h print this help\n", name);
435
436 return 0;
437}
438
439int main(int argc, char **argv)
440{
441 if (freopen("/dev/zero", "w", stderr) == nullptr) {
442 return EXIT_FAILURE;
443 }
444
445 Pa_Initialize();
446
447 struct stat st;
448
449 /* AV files for testing */
450 const char *af_name = nullptr;
451 const char *vf_name = nullptr;
452 long audio_out_dev_idx = -1;
453
454 int32_t audio_frame_duration = 20;
455#if 0
456 // TODO(mannol): Put this to use.
457 int32_t video_frame_duration = 10;
458#endif
459
460 /* Parse settings */
461CHECK_ARG:
462
463 switch (getopt(argc, argv, "a:b:v:x:o:dh")) {
464 case 'a':
465 af_name = optarg;
466 goto CHECK_ARG;
467
468 case 'b': {
469 char *d;
470 audio_frame_duration = strtol(optarg, &d, 10);
471
472 if (*d) {
473 printf("Invalid value for argument: 'b'");
474 exit(1);
475 }
476
477 goto CHECK_ARG;
478 }
479
480 case 'v':
481 vf_name = optarg;
482 goto CHECK_ARG;
483
484#if 0
485
486 case 'x': {
487 char *d;
488 video_frame_duration = strtol(optarg, &d, 10);
489
490 if (*d) {
491 printf("Invalid value for argument: 'x'");
492 exit(1);
493 }
494
495 goto CHECK_ARG;
496 }
497
498#endif
499
500 case 'o': {
501 char *d;
502 audio_out_dev_idx = strtol(optarg, &d, 10);
503
504 if (*d) {
505 printf("Invalid value for argument: 'o'");
506 exit(1);
507 }
508
509 goto CHECK_ARG;
510 }
511
512 case 'd':
513 return print_audio_devices();
514
515 case 'h':
516 return print_help(argv[0]);
517
518 case '?':
519 exit(1);
520
521 case -1:
522 ;
523 }
524
525 { /* Check files */
526 if (!af_name) {
527 printf("Required audio input file!\n");
528 exit(1);
529 }
530
531 if (!vf_name) {
532 printf("Required video input file!\n");
533 exit(1);
534 }
535
536 /* Check for files */
537 if (stat(af_name, &st) != 0 || !S_ISREG(st.st_mode)) {
538 printf("%s doesn't seem to be a regular file!\n", af_name);
539 exit(1);
540 }
541
542 if (stat(vf_name, &st) != 0 || !S_ISREG(st.st_mode)) {
543 printf("%s doesn't seem to be a regular file!\n", vf_name);
544 exit(1);
545 }
546 }
547
548 if (audio_out_dev_idx < 0) {
549 audio_out_dev_idx = Pa_GetDefaultOutputDevice();
550 }
551
552 const PaDeviceInfo *audio_dev = Pa_GetDeviceInfo(audio_out_dev_idx);
553
554 if (!audio_dev) {
555 fprintf(stderr, "Device under index: %ld invalid", audio_out_dev_idx);
556 return 1;
557 }
558
559 printf("Using audio device: %s\n", audio_dev->name);
560 printf("Using audio file: %s\n", af_name);
561 printf("Using video file: %s\n", vf_name);
562
563 /* START TOX NETWORK */
564
565 Tox *bootstrap;
566 ToxAV *AliceAV;
567 ToxAV *BobAV;
568
569 CallControl AliceCC;
570 CallControl BobCC;
571
572 initialize_tox(&bootstrap, &AliceAV, &AliceCC, &BobAV, &BobCC);
573
574 // TODO(iphydf): Don't depend on toxcore internals
575 Mono_Time *mono_time = (*(Messenger **)bootstrap)->mono_time;
576
577 if (TEST_TRANSFER_A) {
578 SNDFILE *af_handle;
579 SF_INFO af_info;
580
581 printf("\nTrying audio enc/dec...\n");
582
583 memset(&AliceCC, 0, sizeof(CallControl));
584 memset(&BobCC, 0, sizeof(CallControl));
585
586 pthread_mutex_init(AliceCC.arb_mutex, nullptr);
587 pthread_mutex_init(BobCC.arb_mutex, nullptr);
588
589 AliceCC.arb = rb_new(16);
590 BobCC.arb = rb_new(16);
591
592 { /* Call */
593 Toxav_Err_Call rc;
594 toxav_call(AliceAV, 0, 48, 0, &rc);
595
596 if (rc != TOXAV_ERR_CALL_OK) {
597 printf("toxav_call failed: %d\n", rc);
598 exit(1);
599 }
600 }
601
602 while (!BobCC.incoming) {
603 iterate_tox(bootstrap, AliceAV, BobAV, nullptr);
604 }
605
606 { /* Answer */
607 Toxav_Err_Answer rc;
608 toxav_answer(BobAV, 0, 48, 0, &rc);
609
610 if (rc != TOXAV_ERR_ANSWER_OK) {
611 printf("toxav_answer failed: %d\n", rc);
612 exit(1);
613 }
614 }
615
616 while (AliceCC.state == 0) {
617 iterate_tox(bootstrap, AliceAV, BobAV, nullptr);
618 }
619
620 /* Open audio file */
621 af_handle = sf_open(af_name, SFM_READ, &af_info);
622
623 if (af_handle == nullptr) {
624 printf("Failed to open the file.\n");
625 exit(1);
626 }
627
628 int16_t PCM[5760];
629
630 time_t start_time = time(nullptr);
631 time_t expected_time = af_info.frames / af_info.samplerate + 2;
632
633
634 /* Start decode thread */
635 struct toxav_thread_data data = {
636 AliceAV,
637 BobAV,
638 0,
639 };
640
641 pthread_t dect;
642 pthread_create(&dect, nullptr, iterate_toxav, &data);
643 pthread_detach(dect);
644
645 int frame_size = (af_info.samplerate * audio_frame_duration / 1000) * af_info.channels;
646
647 struct PaStreamParameters output;
648 output.device = audio_out_dev_idx;
649 output.channelCount = af_info.channels;
650 output.sampleFormat = paInt16;
651 output.suggestedLatency = audio_dev->defaultHighOutputLatency;
652 output.hostApiSpecificStreamInfo = nullptr;
653
654 PaError err = Pa_OpenStream(&adout, nullptr, &output, af_info.samplerate, frame_size, paNoFlag, nullptr, nullptr);
655
656 if (err != paNoError) {
657 return EXIT_FAILURE;
658 }
659
660 err = Pa_StartStream(adout);
661
662 if (err != paNoError) {
663 return EXIT_FAILURE;
664 }
665
666// toxav_audio_bit_rate_set(AliceAV, 0, 64, false, nullptr);
667
668 /* Start write thread */
669 pthread_t t;
670 pthread_create(&t, nullptr, pa_write_thread, &BobCC);
671 pthread_detach(t);
672
673 printf("Sample rate %d\n", af_info.samplerate);
674
675 while (start_time + expected_time > time(nullptr)) {
676 uint64_t enc_start_time = current_time_monotonic(mono_time);
677 int64_t count = sf_read_short(af_handle, PCM, frame_size);
678
679 if (count > 0) {
680 Toxav_Err_Send_Frame rc;
681
682 if (toxav_audio_send_frame(AliceAV, 0, PCM, count / af_info.channels, af_info.channels, af_info.samplerate,
683 &rc) == false) {
684 printf("Error sending frame of size %ld: %d\n", (long)count, rc);
685 }
686 }
687
688 iterate_tox(bootstrap, AliceAV, BobAV, nullptr);
689 c_sleep((audio_frame_duration - (current_time_monotonic(mono_time) - enc_start_time) - 1));
690 }
691
692 printf("Played file in: %lu; stopping stream...\n", time(nullptr) - start_time);
693
694 Pa_StopStream(adout);
695 sf_close(af_handle);
696
697 { /* Hangup */
698 Toxav_Err_Call_Control rc;
699 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
700
701 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
702 printf("toxav_call_control failed: %d\n", rc);
703 exit(1);
704 }
705 }
706
707 iterate_tox(bootstrap, AliceAV, BobAV, nullptr);
708 assert(BobCC.state == TOXAV_FRIEND_CALL_STATE_FINISHED);
709
710 /* Stop decode thread */
711 data.sig = -1;
712
713 while (data.sig != 1) {
714 sched_yield();
715 }
716
717 pthread_mutex_destroy(AliceCC.arb_mutex);
718 pthread_mutex_destroy(BobCC.arb_mutex);
719
720 void *f = nullptr;
721
722 while (rb_read(AliceCC.arb, &f)) {
723 free(f);
724 }
725
726 while (rb_read(BobCC.arb, &f)) {
727 free(f);
728 }
729
730 printf("Success!");
731 }
732
733 if (TEST_TRANSFER_V) {
734 printf("\nTrying video enc/dec...\n");
735
736 memset(&AliceCC, 0, sizeof(CallControl));
737 memset(&BobCC, 0, sizeof(CallControl));
738
739 { /* Call */
740 Toxav_Err_Call rc;
741 toxav_call(AliceAV, 0, 0, 2000, &rc);
742
743 if (rc != TOXAV_ERR_CALL_OK) {
744 printf("toxav_call failed: %d\n", rc);
745 exit(1);
746 }
747 }
748
749 while (!BobCC.incoming) {
750 iterate_tox(bootstrap, AliceAV, BobAV, nullptr);
751 }
752
753 { /* Answer */
754 Toxav_Err_Answer rc;
755 toxav_answer(BobAV, 0, 0, 5000, &rc);
756
757 if (rc != TOXAV_ERR_ANSWER_OK) {
758 printf("toxav_answer failed: %d\n", rc);
759 exit(1);
760 }
761 }
762
763 iterate_tox(bootstrap, AliceAV, BobAV, nullptr);
764
765 /* Start decode thread */
766 struct toxav_thread_data data = {
767 AliceAV,
768 BobAV,
769 0,
770 };
771
772 pthread_t dect;
773 pthread_create(&dect, nullptr, iterate_toxav, &data);
774 pthread_detach(dect);
775
776 CvCapture *capture = cvCreateFileCapture(vf_name);
777
778 if (!capture) {
779 printf("Failed to open video file: %s\n", vf_name);
780 exit(1);
781 }
782
783#if 0
784 toxav_video_bit_rate_set(AliceAV, 0, 5000, false, nullptr);
785#endif
786
787 time_t start_time = time(nullptr);
788
789 while (start_time + 90 > time(nullptr)) {
790 IplImage *frame = cvQueryFrame(capture);
791
792 if (!frame) {
793 break;
794 }
795
796 send_opencv_img(AliceAV, 0, frame);
797 iterate_tox(bootstrap, AliceAV, BobAV, nullptr);
798 c_sleep(10);
799 }
800
801 cvReleaseCapture(&capture);
802
803 { /* Hangup */
804 Toxav_Err_Call_Control rc;
805 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
806
807 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
808 printf("toxav_call_control failed: %d\n", rc);
809 exit(1);
810 }
811 }
812
813 iterate_tox(bootstrap, AliceAV, BobAV, nullptr);
814 assert(BobCC.state == TOXAV_FRIEND_CALL_STATE_FINISHED);
815
816 /* Stop decode thread */
817 printf("Stopping decode thread\n");
818 data.sig = -1;
819
820 while (data.sig != 1) {
821 sched_yield();
822 }
823
824 printf("Success!");
825 }
826
827
828 Tox *Alice = toxav_get_tox(AliceAV);
829 Tox *Bob = toxav_get_tox(BobAV);
830 toxav_kill(BobAV);
831 toxav_kill(AliceAV);
832 tox_kill(Bob);
833 tox_kill(Alice);
834 tox_kill(bootstrap);
835
836 printf("\nTest successful!\n");
837
838 Pa_Terminate();
839 return 0;
840}