diff options
-rw-r--r-- | toxav/Makefile.inc | 2 | ||||
-rw-r--r-- | toxav/av_test.c | 149 |
2 files changed, 148 insertions, 3 deletions
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc index b61c1ea0..1dbabbcd 100644 --- a/toxav/Makefile.inc +++ b/toxav/Makefile.inc | |||
@@ -36,6 +36,7 @@ libtoxav_la_LIBADD = libtoxcore.la \ | |||
36 | $(AV_LIBS) | 36 | $(AV_LIBS) |
37 | 37 | ||
38 | 38 | ||
39 | |||
39 | noinst_PROGRAMS += av_test | 40 | noinst_PROGRAMS += av_test |
40 | 41 | ||
41 | av_test_SOURCES = ../toxav/av_test.c | 42 | av_test_SOURCES = ../toxav/av_test.c |
@@ -50,6 +51,7 @@ av_test_LDADD = $(LIBSODIUM_LDFLAGS) \ | |||
50 | $(LIBSODIUM_LIBS) \ | 51 | $(LIBSODIUM_LIBS) \ |
51 | $(NACL_OBJECTS) \ | 52 | $(NACL_OBJECTS) \ |
52 | -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 \ | ||
53 | $(NACL_LIBS) | 55 | $(NACL_LIBS) |
54 | 56 | ||
55 | 57 | ||
diff --git a/toxav/av_test.c b/toxav/av_test.c index 42b2fcc4..249e0ab7 100644 --- a/toxav/av_test.c +++ b/toxav/av_test.c | |||
@@ -13,6 +13,11 @@ | |||
13 | # endif /* ALC_ALL_DEVICES_SPECIFIER */ | 13 | # endif /* ALC_ALL_DEVICES_SPECIFIER */ |
14 | #endif /* __APPLE__ */ | 14 | #endif /* __APPLE__ */ |
15 | 15 | ||
16 | #include <opencv/cv.h> | ||
17 | #include <opencv/highgui.h> | ||
18 | |||
19 | #include <vpx/vpx_image.h> | ||
20 | |||
16 | #include <assert.h> | 21 | #include <assert.h> |
17 | #include <stdio.h> | 22 | #include <stdio.h> |
18 | #include <stdlib.h> | 23 | #include <stdlib.h> |
@@ -26,7 +31,6 @@ | |||
26 | #define c_sleep(x) usleep(1000*x) | 31 | #define c_sleep(x) usleep(1000*x) |
27 | #endif | 32 | #endif |
28 | 33 | ||
29 | #define MIN(a,b) (((a)<(b))?(a):(b)) | ||
30 | 34 | ||
31 | /* Enable/disable tests */ | 35 | /* Enable/disable tests */ |
32 | #define TEST_REGULAR_AV 0 | 36 | #define TEST_REGULAR_AV 0 |
@@ -35,7 +39,8 @@ | |||
35 | #define TEST_REJECT 0 | 39 | #define TEST_REJECT 0 |
36 | #define TEST_CANCEL 0 | 40 | #define TEST_CANCEL 0 |
37 | #define TEST_MUTE_UNMUTE 0 | 41 | #define TEST_MUTE_UNMUTE 0 |
38 | #define TEST_TRANSFER_A 1 | 42 | #define TEST_TRANSFER_A 0 |
43 | #define TEST_TRANSFER_V 1 | ||
39 | 44 | ||
40 | 45 | ||
41 | typedef struct { | 46 | typedef struct { |
@@ -44,6 +49,8 @@ typedef struct { | |||
44 | uint32_t output_source; | 49 | uint32_t output_source; |
45 | } CallControl; | 50 | } CallControl; |
46 | 51 | ||
52 | const char* video_test_window = "AV Test"; | ||
53 | |||
47 | const char* stringify_state(TOXAV_CALL_STATE s) | 54 | const char* stringify_state(TOXAV_CALL_STATE s) |
48 | { | 55 | { |
49 | static const char* strings[] = | 56 | static const char* strings[] = |
@@ -82,7 +89,36 @@ void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, | |||
82 | uint8_t const *planes[], int32_t const stride[], | 89 | uint8_t const *planes[], int32_t const stride[], |
83 | void *user_data) | 90 | void *user_data) |
84 | { | 91 | { |
85 | printf("Handling VIDEO FRAME callback\n"); | 92 | IplImage output_img; |
93 | const int bpl = stride[VPX_PLANE_Y]; | ||
94 | const int cxbpl = stride[VPX_PLANE_V]; | ||
95 | |||
96 | output_img.imageData = malloc(width * height * 3); | ||
97 | output_img.imageSize = width * height * 3; | ||
98 | output_img.width = width; | ||
99 | output_img.height = height; | ||
100 | |||
101 | /* FIXME: possible bug? */ | ||
102 | const uint8_t* yData = planes[VPX_PLANE_Y]; | ||
103 | const uint8_t* uData = planes[VPX_PLANE_V]; | ||
104 | const uint8_t* vData = planes[VPX_PLANE_U]; | ||
105 | |||
106 | // convert from planar to packed | ||
107 | for (int y = 0; y < height; ++y) | ||
108 | { | ||
109 | for (int x = 0; x < width; ++x) | ||
110 | { | ||
111 | 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]; | ||
113 | uint8_t V = planes[VPX_PLANE_U][x/(1 << 1) + y/(1 << 1)*cxbpl]; | ||
114 | output_img.imageData[width * 3 * y + x * 3 + 0] = Y; | ||
115 | output_img.imageData[width * 3 * y + x * 3 + 1] = U; | ||
116 | output_img.imageData[width * 3 * y + x * 3 + 2] = V; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | cvShowImage(video_test_window, &output_img); | ||
121 | free(output_img.imageData); | ||
86 | } | 122 | } |
87 | void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, | 123 | void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, |
88 | int16_t const *pcm, | 124 | int16_t const *pcm, |
@@ -265,8 +301,84 @@ long get_device_idx(const char* arg) | |||
265 | return res; | 301 | return res; |
266 | } | 302 | } |
267 | 303 | ||
304 | int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img) | ||
305 | { | ||
306 | /* I use vpx image coz i'm noob TODO use opencv conversion */ | ||
307 | vpx_image vpx_img; | ||
308 | vpx_img.w = vpx_img.h = vpx_img.d_w = vpx_img.d_h = 0; | ||
309 | |||
310 | const int w = img->width; | ||
311 | const int h = img->height; | ||
312 | |||
313 | vpx_img_alloc(&vpx_img, VPX_IMG_FMT_VPXI420, w, h, 1); | ||
314 | |||
315 | for (int y = 0; y < h; ++y) | ||
316 | { | ||
317 | for (int x = 0; x < w; ++x) | ||
318 | { | ||
319 | uint8_t b = img->imageData[(x + y * w) * 3 + 0]; | ||
320 | uint8_t g = img->imageData[(x + y * w) * 3 + 1]; | ||
321 | uint8_t r = img->imageData[(x + y * w) * 3 + 2]; | ||
322 | |||
323 | vpx_img.planes[VPX_PLANE_Y][x + y * vpx_img.stride[VPX_PLANE_Y]] = ((66 * r + 129 * g + 25 * b) >> 8) + 16; | ||
324 | |||
325 | if (!(x % (1 << vpx_img.x_chroma_shift)) && !(y % (1 << vpx_img.y_chroma_shift))) | ||
326 | { | ||
327 | const int i = x / (1 << vpx_img.x_chroma_shift); | ||
328 | const int j = y / (1 << vpx_img.y_chroma_shift); | ||
329 | vpx_img.planes[VPX_PLANE_U][i + j * vpx_img.stride[VPX_PLANE_U]] = ((112 * r + -94 * g + -18 * b) >> 8) + 128; | ||
330 | vpx_img.planes[VPX_PLANE_V][i + j * vpx_img.stride[VPX_PLANE_V]] = ((-38 * r + -74 * g + 112 * b) >> 8) + 128; | ||
331 | } | ||
332 | } | ||
333 | } | ||
334 | |||
335 | int rc = toxav_send_video_frame(av, friend_number, w, h, | ||
336 | vpx_img.planes[VPX_PLANE_Y], | ||
337 | vpx_img.planes[VPX_PLANE_U], | ||
338 | vpx_img.planes[VPX_PLANE_V], NULL); | ||
339 | |||
340 | vpx_img_free(&vpx_img); | ||
341 | return rc; | ||
342 | } | ||
343 | |||
268 | int main (int argc, char** argv) | 344 | int main (int argc, char** argv) |
269 | { | 345 | { |
346 | /* AV files for testing */ | ||
347 | const char* audio_in = ""; | ||
348 | const char* video_in = ""; | ||
349 | long audio_out_dev = 0; | ||
350 | |||
351 | AGAIN: | ||
352 | switch (getopt(argc, argv, "a:v:o:")) | ||
353 | { | ||
354 | case 'a': | ||
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 | } | ||
377 | |||
378 | |||
379 | |||
380 | return 0; | ||
381 | |||
270 | if (argc == 2) { | 382 | if (argc == 2) { |
271 | if (strcmp(argv[1], "-d") == 0 || strcmp(argv[1], "--devices") == 0) { | 383 | if (strcmp(argv[1], "-d") == 0 || strcmp(argv[1], "--devices") == 0) { |
272 | return print_devices(); | 384 | return print_devices(); |
@@ -675,6 +787,37 @@ int main (int argc, char** argv) | |||
675 | printf("Success!"); | 787 | printf("Success!"); |
676 | } | 788 | } |
677 | 789 | ||
790 | if (TEST_TRANSFER_V) { | ||
791 | if (strlen(video_in) == 0) { | ||
792 | printf("Skipping video test...\n"); | ||
793 | goto CONTINUE; | ||
794 | } | ||
795 | |||
796 | cvNamedWindow(video_test_window, CV_WINDOW_AUTOSIZE); | ||
797 | |||
798 | CvCapture* capture = cvCreateFileCapture(video_in); | ||
799 | if (!capture) { | ||
800 | printf("No file named: %s\n", video_in); | ||
801 | return 1; | ||
802 | } | ||
803 | |||
804 | IplImage* frame; | ||
805 | time_t start_time = time(NULL); | ||
806 | |||
807 | while(start_time + 10 > time(NULL)) { | ||
808 | frame = cvQueryFrame( capture ); | ||
809 | if (!frame) | ||
810 | break; | ||
811 | |||
812 | } | ||
813 | |||
814 | cvReleaseCapture(&capture); | ||
815 | cvDestroyWindow(video_test_window); | ||
816 | |||
817 | CONTINUE:; | ||
818 | } | ||
819 | |||
820 | |||
678 | toxav_kill(BobAV); | 821 | toxav_kill(BobAV); |
679 | toxav_kill(AliceAV); | 822 | toxav_kill(AliceAV); |
680 | tox_kill(Bob); | 823 | tox_kill(Bob); |