summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-04-02 02:04:45 +0200
committermannol <eniz_vukovic@hotmail.com>2015-04-02 02:04:45 +0200
commit62c4fd7409c47a30a8290c0bd1c486ad4b4b1973 (patch)
treee43db9a39f1c7a8448b16683a86473b2ee935be5 /toxav
parentfdaad0b7c008b65646ca5cbd62ac0d305617ecfe (diff)
Video preview works (lmao)
Diffstat (limited to 'toxav')
-rw-r--r--toxav/Makefile.inc8
-rw-r--r--toxav/av_test.c234
-rw-r--r--toxav/codec.c17
-rw-r--r--toxav/toxav.c3
4 files changed, 176 insertions, 86 deletions
diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc
index 8e2be25e..a73ddc91 100644
--- a/toxav/Makefile.inc
+++ b/toxav/Makefile.inc
@@ -37,14 +37,14 @@ libtoxav_la_LIBADD = libtoxcore.la \
37 37
38 38
39 39
40noinst_PROGRAMS += av_test 40#noinst_PROGRAMS += av_test
41 41
42av_test_SOURCES = ../toxav/av_test.c 42#av_test_SOURCES = ../toxav/av_test.c
43 43
44av_test_CFLAGS = $(LIBSODIUM_CFLAGS) \ 44#av_test_CFLAGS = $(LIBSODIUM_CFLAGS) \
45 $(NACL_CFLAGS) 45 $(NACL_CFLAGS)
46 46
47av_test_LDADD = $(LIBSODIUM_LDFLAGS) \ 47#av_test_LDADD = $(LIBSODIUM_LDFLAGS) \
48 $(NACL_LDFLAGS) \ 48 $(NACL_LDFLAGS) \
49 libtoxav.la \ 49 libtoxav.la \
50 libtoxcore.la \ 50 libtoxcore.la \
diff --git a/toxav/av_test.c b/toxav/av_test.c
index f0ad6a01..b7260d7d 100644
--- a/toxav/av_test.c
+++ b/toxav/av_test.c
@@ -1,4 +1,4 @@
1#include "toxav.h" 1#include "../toxav/toxav.h"
2#include "../toxcore/tox.h" 2#include "../toxcore/tox.h"
3 3
4/* For playing audio data */ 4/* For playing audio data */
@@ -11,9 +11,7 @@
11/* For reading and displaying video data */ 11/* For reading and displaying video data */
12#include <opencv/cv.h> 12#include <opencv/cv.h>
13#include <opencv/highgui.h> 13#include <opencv/highgui.h>
14 14#include <opencv/cvwimage.h>
15/* For converting images TODO remove */
16#include <vpx/vpx_image.h>
17 15
18 16
19#include <sys/stat.h> 17#include <sys/stat.h>
@@ -29,6 +27,23 @@
29#define c_sleep(x) usleep(1000*x) 27#define c_sleep(x) usleep(1000*x)
30 28
31 29
30#define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X)
31
32// RGB -> YUV
33#define RGB2Y(R, G, B) CLIP(( ( 66 * (R) + 129 * (G) + 25 * (B) + 128) >> 8) + 16)
34#define RGB2U(R, G, B) CLIP(( ( -38 * (R) - 74 * (G) + 112 * (B) + 128) >> 8) + 128)
35#define RGB2V(R, G, B) CLIP(( ( 112 * (R) - 94 * (G) - 18 * (B) + 128) >> 8) + 128)
36
37// YUV -> RGB
38#define C(Y) ( (Y) - 16 )
39#define D(U) ( (U) - 128 )
40#define E(V) ( (V) - 128 )
41
42#define YUV2R(Y, U, V) CLIP(( 298 * C(Y) + 409 * E(V) + 128) >> 8)
43#define YUV2G(Y, U, V) CLIP(( 298 * C(Y) - 100 * D(U) - 208 * E(V) + 128) >> 8)
44#define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U) + 128) >> 8)
45
46
32/* Enable/disable tests */ 47/* Enable/disable tests */
33#define TEST_REGULAR_AV 0 48#define TEST_REGULAR_AV 0
34#define TEST_REGULAR_A 0 49#define TEST_REGULAR_A 0
@@ -36,8 +51,8 @@
36#define TEST_REJECT 0 51#define TEST_REJECT 0
37#define TEST_CANCEL 0 52#define TEST_CANCEL 0
38#define TEST_MUTE_UNMUTE 0 53#define TEST_MUTE_UNMUTE 0
39#define TEST_TRANSFER_A 1 54#define TEST_TRANSFER_A 0
40#define TEST_TRANSFER_V 0 55#define TEST_TRANSFER_V 1
41 56
42 57
43typedef struct { 58typedef struct {
@@ -83,38 +98,32 @@ void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
83 uint8_t const *planes[], int32_t const stride[], 98 uint8_t const *planes[], int32_t const stride[],
84 void *user_data) 99 void *user_data)
85{ 100{
86 IplImage output_img; 101 uint16_t *img_data = malloc(height * width * 6);
87 const int bpl = stride[VPX_PLANE_Y]; 102
88 const int cxbpl = stride[VPX_PLANE_V]; 103 unsigned long int i, j;
89 104 for (i = 0; i < height; ++i) {
90 output_img.imageData = malloc(width * height * 3); 105 for (j = 0; j < width; ++j) {
91 output_img.imageSize = width * height * 3; 106 uint8_t *point = (void*)img_data + 3 * ((i * width) + j);
92 output_img.width = width; 107 int y = planes[0][(i * stride[0]) + j];
93 output_img.height = height; 108 int u = planes[1][((i / 2) * stride[1]) + (j / 2)];
94 109 int v = planes[2][((i / 2) * stride[2]) + (j / 2)];
95 /* FIXME: possible bug? */ 110
96 const uint8_t* yData = planes[VPX_PLANE_Y]; 111 point[0] = YUV2R(y, u, v);
97 const uint8_t* uData = planes[VPX_PLANE_V]; 112 point[1] = YUV2G(y, u, v);
98 const uint8_t* vData = planes[VPX_PLANE_U]; 113 point[2] = YUV2B(y, u, v);
99
100 // convert from planar to packed
101 int y = 0;
102 for (; y < height; ++y)
103 {
104 int x = 0;
105 for (; x < width; ++x)
106 {
107 uint8_t Y = planes[VPX_PLANE_Y][x + y * bpl];
108 uint8_t U = planes[VPX_PLANE_V][x/(1 << 1) + y/(1 << 1)*cxbpl];
109 uint8_t V = planes[VPX_PLANE_U][x/(1 << 1) + y/(1 << 1)*cxbpl];
110 output_img.imageData[width * 3 * y + x * 3 + 0] = Y;
111 output_img.imageData[width * 3 * y + x * 3 + 1] = U;
112 output_img.imageData[width * 3 * y + x * 3 + 2] = V;
113 } 114 }
114 } 115 }
115 116
116 cvShowImage(vdout, &output_img); 117
117 free(output_img.imageData); 118 CvMat mat = cvMat(height, width, CV_8UC3, img_data);
119
120 CvSize sz = {.height = height, .width = width};
121
122 IplImage* header = cvCreateImageHeader(sz, 1, 3);
123 IplImage* img = cvGetImage(&mat, header);
124 cvShowImage(vdout, img);
125 cvWaitKey(1);
126 free(img_data);
118} 127}
119void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, 128void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
120 int16_t const *pcm, 129 int16_t const *pcm,
@@ -140,7 +149,7 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
140 return; 149 return;
141 150
142 151
143 alBufferData(bufid, channels == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, 152 alBufferData(bufid, channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
144 pcm, sample_count * 2, sampling_rate); 153 pcm, sample_count * 2, sampling_rate);
145 alSourceQueueBuffers(adout, 1, &bufid); 154 alSourceQueueBuffers(adout, 1, &bufid);
146 155
@@ -244,45 +253,42 @@ int iterate_tox(Tox* bootstrap, ToxAV* AliceAV, ToxAV* BobAV)
244} 253}
245 254
246int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img) 255int send_opencv_img(ToxAV* av, uint32_t friend_number, const IplImage* img)
247{ 256{
248 /* I use vpx image coz i'm noob TODO use opencv conversion */ 257 int32_t strides[3] = { 1280, 640, 640 };
249 vpx_image_t vpx_img; 258 uint8_t* planes[3] = {
250 vpx_img.w = vpx_img.h = vpx_img.d_w = vpx_img.d_h = 0; 259 malloc(img->height * img->width),
251 260 malloc(img->height * img->width / 2),
252 const int w = img->width; 261 malloc(img->height * img->width / 2),
253 const int h = img->height; 262 };
254 263
255 vpx_img_alloc(&vpx_img, VPX_IMG_FMT_VPXI420, w, h, 1); 264 int x_chroma_shift = 1;
265 int y_chroma_shift = 1;
256 266
257 int y = 0; 267 int x, y;
258 for (; y < h; ++y) 268 for (y = 0; y < img->height; ++y) {
259 { 269 for (x = 0; x < img->width; ++x) {
260 int x = 0; 270 uint8_t r = img->imageData[(x + y * img->width) * 3 + 0];
261 for (; x < w; ++x) 271 uint8_t g = img->imageData[(x + y * img->width) * 3 + 1];
262 { 272 uint8_t b = img->imageData[(x + y * img->width) * 3 + 2];
263 uint8_t b = img->imageData[(x + y * w) * 3 + 0];
264 uint8_t g = img->imageData[(x + y * w) * 3 + 1];
265 uint8_t r = img->imageData[(x + y * w) * 3 + 2];
266 273
267 vpx_img.planes[VPX_PLANE_Y][x + y * vpx_img.stride[VPX_PLANE_Y]] = ((66 * r + 129 * g + 25 * b) >> 8) + 16; 274 planes[0][x + y * strides[0]] = RGB2Y(r, g, b);
268 275 if (!(x % (1 << x_chroma_shift)) && !(y % (1 << y_chroma_shift))) {
269 if (!(x % (1 << vpx_img.x_chroma_shift)) && !(y % (1 << vpx_img.y_chroma_shift))) 276 const int i = x / (1 << x_chroma_shift);
270 { 277 const int j = y / (1 << y_chroma_shift);
271 const int i = x / (1 << vpx_img.x_chroma_shift); 278 planes[1][i + j * strides[1]] = RGB2U(r, g, b);
272 const int j = y / (1 << vpx_img.y_chroma_shift); 279 planes[2][i + j * strides[2]] = RGB2V(r, g, b);
273 vpx_img.planes[VPX_PLANE_U][i + j * vpx_img.stride[VPX_PLANE_U]] = ((112 * r + -94 * g + -18 * b) >> 8) + 128;
274 vpx_img.planes[VPX_PLANE_V][i + j * vpx_img.stride[VPX_PLANE_V]] = ((-38 * r + -74 * g + 112 * b) >> 8) + 128;
275 } 280 }
276 } 281 }
277 } 282 }
278 283
279 int rc = toxav_send_video_frame(av, friend_number, w, h,
280 vpx_img.planes[VPX_PLANE_Y],
281 vpx_img.planes[VPX_PLANE_U],
282 vpx_img.planes[VPX_PLANE_V], NULL);
283 284
284 vpx_img_free(&vpx_img); 285// int rc = toxav_send_video_frame(av, friend_number, img->width, img->height, planes[0], planes[1], planes[2], NULL);
285 return rc; 286 t_toxav_receive_video_frame_cb(av, 0, img->width, img->height, (const uint8_t**) planes, strides, NULL);
287 free(planes[0]);
288 free(planes[1]);
289 free(planes[2]);
290// return rc;
291 return 0;
286} 292}
287 293
288ALCdevice* open_audio_device(const char* audio_out_dev_name) 294ALCdevice* open_audio_device(const char* audio_out_dev_name)
@@ -403,6 +409,32 @@ int main (int argc, char** argv)
403 } 409 }
404 } 410 }
405 411
412
413 cvNamedWindow(vdout, CV_WINDOW_AUTOSIZE);
414
415 CvCapture* capture = cvCreateFileCapture(vf_name);
416 if (!capture) {
417 printf("Failed to open video file: %s\n", vf_name);
418 exit(1);
419 }
420
421 IplImage* frame;
422 time_t start_time = time(NULL);
423
424 int frame_rate = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
425 while(start_time + 4 > time(NULL)) {
426 frame = cvQueryFrame( capture );
427 if (!frame)
428 break;
429
430 send_opencv_img(NULL, 0, frame);
431 c_sleep(1);
432 }
433
434 cvReleaseCapture(&capture);
435 cvDestroyWindow(vdout);
436
437 return 0;
406 const char* audio_out_dev_name = NULL; 438 const char* audio_out_dev_name = NULL;
407 439
408 int i = 0; 440 int i = 0;
@@ -706,19 +738,19 @@ int main (int argc, char** argv)
706 time_t expected_time = af_info.frames / af_info.samplerate + 2; 738 time_t expected_time = af_info.frames / af_info.samplerate + 2;
707 739
708 while ( start_time + expected_time > time(NULL) ) { 740 while ( start_time + expected_time > time(NULL) ) {
709 int frame_size = (af_info.samplerate * frame_duration / 1000); 741 int frame_size = (af_info.samplerate * frame_duration / 1000) * af_info.channels;
710 742
711 int64_t count = sf_read_short(af_handle, PCM, frame_size); 743 int64_t count = sf_read_short(af_handle, PCM, frame_size);
712 if (count > 0) { 744 if (count > 0) {
713 t_toxav_receive_audio_frame_cb(BobAV, 0, PCM, count, af_info.channels, af_info.samplerate, NULL); 745// t_toxav_receive_audio_frame_cb(AliceAV, 0, PCM, count, af_info.channels, af_info.samplerate, NULL);
714// TOXAV_ERR_SEND_FRAME rc; 746 TOXAV_ERR_SEND_FRAME rc;
715// if (toxav_send_audio_frame(AliceAV, 0, PCM, count, af_info.channels, af_info.samplerate, &rc) == false) { 747 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); 748 printf("Error sending frame of size %ld: %d\n", count, rc);
717// exit(1); 749 exit(1);
718// } 750 }
719 } 751 }
720 c_sleep(frame_duration); 752 iterate_tox(bootstrap, AliceAV, BobAV);
721// iterate_tox(bootstrap, AliceAV, BobAV); 753// c_sleep(frame_duration);
722 } 754 }
723 755
724 756
@@ -744,6 +776,36 @@ int main (int argc, char** argv)
744 } 776 }
745 777
746 if (TEST_TRANSFER_V) { 778 if (TEST_TRANSFER_V) {
779 printf("\nTrying video enc/dec...\n");
780
781 memset(&AliceCC, 0, sizeof(CallControl));
782 memset(&BobCC, 0, sizeof(CallControl));
783
784 { /* Call */
785 TOXAV_ERR_CALL rc;
786 toxav_call(AliceAV, 0, 0, 500000, &rc);
787
788 if (rc != TOXAV_ERR_CALL_OK) {
789 printf("toxav_call failed: %d\n", rc);
790 exit(1);
791 }
792 }
793
794 while (!BobCC.incoming)
795 iterate_tox(bootstrap, AliceAV, BobAV);
796
797 { /* Answer */
798 TOXAV_ERR_ANSWER rc;
799 toxav_answer(BobAV, 0, 0, 500000, &rc);
800
801 if (rc != TOXAV_ERR_ANSWER_OK) {
802 printf("toxav_answer failed: %d\n", rc);
803 exit(1);
804 }
805 }
806
807 iterate_tox(bootstrap, AliceAV, BobAV);
808
747 cvNamedWindow(vdout, CV_WINDOW_AUTOSIZE); 809 cvNamedWindow(vdout, CV_WINDOW_AUTOSIZE);
748 810
749 CvCapture* capture = cvCreateFileCapture(vf_name); 811 CvCapture* capture = cvCreateFileCapture(vf_name);
@@ -755,15 +817,35 @@ int main (int argc, char** argv)
755 IplImage* frame; 817 IplImage* frame;
756 time_t start_time = time(NULL); 818 time_t start_time = time(NULL);
757 819
820 int frame_rate = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
758 while(start_time + 10 > time(NULL)) { 821 while(start_time + 10 > time(NULL)) {
759 frame = cvQueryFrame( capture ); 822 frame = cvQueryFrame( capture );
760 if (!frame) 823 if (!frame)
761 break; 824 break;
762 825
826// cvShowImage(vdout, frame);
827// cvWaitKey(frame_rate);
828 send_opencv_img(AliceAV, 0, frame);
829 iterate_tox(bootstrap, AliceAV, BobAV);
763 } 830 }
764 831
765 cvReleaseCapture(&capture); 832 cvReleaseCapture(&capture);
766 cvDestroyWindow(vdout); 833 cvDestroyWindow(vdout);
834
835 { /* Hangup */
836 TOXAV_ERR_CALL_CONTROL rc;
837 toxav_call_control(AliceAV, 0, TOXAV_CALL_CONTROL_CANCEL, &rc);
838
839 if (rc != TOXAV_ERR_CALL_CONTROL_OK) {
840 printf("toxav_call_control failed: %d\n", rc);
841 exit(1);
842 }
843 }
844
845 iterate_tox(bootstrap, AliceAV, BobAV);
846 assert(BobCC.state == TOXAV_CALL_STATE_END);
847
848 printf("Success!");
767 } 849 }
768 850
769 851
diff --git a/toxav/codec.c b/toxav/codec.c
index b0f2ed31..4ae5a10b 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -337,12 +337,14 @@ void cs_do(CSession *cs)
337 pthread_mutex_unlock(cs->queue_mutex); 337 pthread_mutex_unlock(cs->queue_mutex);
338 338
339 if (success == 2) { 339 if (success == 2) {
340 LOGGER_DEBUG("OPUS correction");
340 rc = opus_decode(cs->audio_decoder, NULL, 0, tmp, 341 rc = opus_decode(cs->audio_decoder, NULL, 0, tmp,
341 cs->last_packet_sampling_rate * cs->last_packet_frame_duration / 1000, 1); 342 (cs->last_packet_sampling_rate * cs->last_packet_frame_duration / 1000) *
343 cs->last_packet_channel_count, 1);
342 } else { 344 } else {
343 /* Get values from packet and decode. 345 /* Get values from packet and decode.
344 * It also checks for validity of an opus packet 346 * It also checks for validity of an opus packet
345 */ 347 */
346 rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data)); 348 rc = convert_bw_to_sampling_rate(opus_packet_get_bandwidth(msg->data));
347 if (rc != -1) { 349 if (rc != -1) {
348 cs->last_packet_sampling_rate = rc; 350 cs->last_packet_sampling_rate = rc;
@@ -351,6 +353,9 @@ void cs_do(CSession *cs)
351 cs->last_packet_frame_duration = 353 cs->last_packet_frame_duration =
352 ( opus_packet_get_samples_per_frame(msg->data, cs->last_packet_sampling_rate) * 1000 ) 354 ( opus_packet_get_samples_per_frame(msg->data, cs->last_packet_sampling_rate) * 1000 )
353 / cs->last_packet_sampling_rate; 355 / cs->last_packet_sampling_rate;
356
357 /* TODO FIXME WARNING calculate properly according to propper channel count */
358 cs->last_packet_frame_duration /= cs->last_packet_channel_count;
354 } else { 359 } else {
355 LOGGER_WARNING("Failed to load packet values!"); 360 LOGGER_WARNING("Failed to load packet values!");
356 rtp_free_msg(NULL, msg); 361 rtp_free_msg(NULL, msg);
@@ -433,7 +438,7 @@ CSession *cs_new(uint32_t peer_video_frame_piece_size)
433 */ 438 */
434 439
435 int status; 440 int status;
436 cs->audio_decoder = opus_decoder_create(48000, 2, &status ); /* NOTE: Must be mono */ 441 cs->audio_decoder = opus_decoder_create(48000, 1, &status ); /* NOTE: Must be mono */
437 442
438 if ( status != OPUS_OK ) { 443 if ( status != OPUS_OK ) {
439 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(status)); 444 LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(status));
@@ -472,6 +477,10 @@ CSession *cs_new(uint32_t peer_video_frame_piece_size)
472 vpx_codec_destroy(cs->v_decoder); 477 vpx_codec_destroy(cs->v_decoder);
473 goto AUDIO_DECODER_CLEANUP; 478 goto AUDIO_DECODER_CLEANUP;
474 } 479 }
480
481 if ( !(cs->split_video_frame = calloc(VIDEOFRAME_PIECE_SIZE + VIDEOFRAME_HEADER_SIZE, 1)) )
482 goto FAILURE;
483
475 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 484 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
476 485
477 /* Initialize encoders with default values */ 486 /* Initialize encoders with default values */
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 62fed33f..9febd3a9 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -700,9 +700,8 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
700 goto END; 700 goto END;
701 } 701 }
702 702
703
704 LOGGER_DEBUG("Sending audio frame size: %d; channels: %d; srate: %d", sample_count, channels, sampling_rate); 703 LOGGER_DEBUG("Sending audio frame size: %d; channels: %d; srate: %d", sample_count, channels, sampling_rate);
705 uint8_t dest[sample_count * channels * 2 /* sizeof(uint16_t) */]; 704 uint8_t dest[sample_count * channels * sizeof(int16_t)];
706 int vrc = opus_encode(call->cs->audio_encoder, pcm, sample_count, dest, sizeof (dest)); 705 int vrc = opus_encode(call->cs->audio_encoder, pcm, sample_count, dest, sizeof (dest));
707 706
708 if (vrc < 0) { 707 if (vrc < 0) {