summaryrefslogtreecommitdiff
path: root/toxav/phone.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/phone.c')
-rwxr-xr-xtoxav/phone.c704
1 files changed, 606 insertions, 98 deletions
diff --git a/toxav/phone.c b/toxav/phone.c
index 6d4b5e6b..8a0a3162 100755
--- a/toxav/phone.c
+++ b/toxav/phone.c
@@ -35,18 +35,25 @@
35#endif /* HAVE_CONFIG_H */ 35#endif /* HAVE_CONFIG_H */
36 36
37#define _BSD_SOURCE 37#define _BSD_SOURCE
38#define _GNU_SOURCE
38 39
39#include <stdio.h> 40#include <stdio.h>
40#include <string.h> 41#include <string.h>
41#include <stdlib.h> 42#include <stdlib.h>
42
43#include "toxmsi.h"
44#include "toxrtp.h"
45#include <stdarg.h> 43#include <stdarg.h>
46#include <unistd.h> 44#include <unistd.h>
47#include <assert.h> 45#include <assert.h>
46#include <math.h>
47#include <AL/al.h>
48#include <AL/alc.h>
49#include <SDL/SDL.h>
50#include <SDL/SDL_thread.h>
51#include <pthread.h>
52#include <opus/opus.h>
48 53
49#include "../toxcore/network.h" 54#include "toxmsi.h"
55#include "toxrtp.h"
56#include "toxmedia.h"
50#include "../toxcore/event.h" 57#include "../toxcore/event.h"
51#include "../toxcore/tox.h" 58#include "../toxcore/tox.h"
52 59
@@ -54,6 +61,14 @@
54#define _USERAGENT "v.0.3.0" 61#define _USERAGENT "v.0.3.0"
55 62
56 63
64struct SDL_Surface *screen;
65
66typedef struct {
67 struct SDL_Overlay *bmp;
68 int width, height;
69} VideoPicture;
70
71
57typedef struct av_friend_s { 72typedef struct av_friend_s {
58 int _id; 73 int _id;
59 int _active; /* 0=false; 1=true; */ 74 int _active; /* 0=false; 1=true; */
@@ -61,16 +76,30 @@ typedef struct av_friend_s {
61 76
62typedef struct av_session_s { 77typedef struct av_session_s {
63 MSISession* _msi; 78 MSISession* _msi;
64
65 RTPSession* _rtp_audio; 79 RTPSession* _rtp_audio;
66 RTPSession* _rtp_video; 80 RTPSession* _rtp_video;
67 81
82 /* Encoding/decoding/capturing/playing */
83
84 codec_state* cs;
85 VideoPicture video_picture;
86 struct ALCdevice *audio_capture_device;
87
88 /* context for converting image format to something SDL can use*/
89 struct SwsContext *sws_SDL_r_ctx;
90
91 /* context for converting webcam image format to something the video encoder can use */
92 struct SwsContext *sws_ctx;
93
94 /**/
95
96
68 pthread_mutex_t _mutex; 97 pthread_mutex_t _mutex;
69 98
70 Tox* _messenger; 99 Tox* _messenger;
71 av_friend_t* _friends; 100 av_friend_t* _friends;
72 int _friend_cout; 101 int _friend_cout;
73 uint8_t _my_public_id[200]; 102 char _my_public_id[200];
74} av_session_t; 103} av_session_t;
75 104
76 105
@@ -86,7 +115,7 @@ void av_allocate_friend(av_session_t* _phone, int _id, int _active)
86 _phone->_friends = realloc(_phone->_friends, sizeof(av_friend_t) * _phone->_friend_cout); 115 _phone->_friends = realloc(_phone->_friends, sizeof(av_friend_t) * _phone->_friend_cout);
87 } 116 }
88 117
89 if ( _id = -1 ) { 118 if ( _id == -1 ) {
90 _phone->_friends->_id = _new_id; 119 _phone->_friends->_id = _new_id;
91 _new_id ++; 120 _new_id ++;
92 } else _phone->_friends->_id = _id; 121 } else _phone->_friends->_id = _id;
@@ -174,7 +203,7 @@ char* trim_spaces ( char* buff )
174 203
175static void fraddr_to_str(uint8_t *id_bin, char *id_str) 204static void fraddr_to_str(uint8_t *id_bin, char *id_str)
176{ 205{
177 uint i, delta = 0, pos_extra, sum_extra = 0; 206 uint i, delta = 0, pos_extra = 0, sum_extra = 0;
178 207
179 for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { 208 for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) {
180 sprintf(&id_str[2 * i + delta], "%02hhX", id_bin[i]); 209 sprintf(&id_str[2 * i + delta], "%02hhX", id_bin[i]);
@@ -197,127 +226,526 @@ static void fraddr_to_str(uint8_t *id_bin, char *id_str)
197 id_str[pos_extra] = 0; 226 id_str[pos_extra] = 0;
198} 227}
199 228
200void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) 229/*********************************************
201{ 230 *********************************************
202 RTPMessage* _audio_msg, * _video_msg; 231 *********************************************
203 av_session_t* _phone = _hmtc_args_p; 232 *********************************************
204 MSISession* _session = _phone->_msi; 233 *********************************************
234 *********************************************
235 *********************************************
236 *********************************************
237 */
205 238
206 RTPSession* _rtp_audio = _phone->_rtp_audio;
207 RTPSession* _rtp_video = _phone->_rtp_video;
208 239
209 240/*
210 Tox* _messenger = _phone->_messenger; 241 * How av stuff _should_ look like
242 */
243
244int display_received_frame(av_session_t* _phone, AVFrame *r_video_frame)
245{
246 codec_state* cs = _phone->cs;
247 AVPicture pict;
248 SDL_LockYUVOverlay(_phone->video_picture.bmp);
249
250 pict.data[0] = _phone->video_picture.bmp->pixels[0];
251 pict.data[1] = _phone->video_picture.bmp->pixels[2];
252 pict.data[2] = _phone->video_picture.bmp->pixels[1];
253 pict.linesize[0] = _phone->video_picture.bmp->pitches[0];
254 pict.linesize[1] = _phone->video_picture.bmp->pitches[2];
255 pict.linesize[2] = _phone->video_picture.bmp->pitches[1];
211 256
257 /* Convert the image into YUV format that SDL uses */
258 sws_scale(_phone->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0,
259 cs->video_decoder_ctx->height, pict.data, pict.linesize );
212 260
213 while ( _session->call ) { 261 SDL_UnlockYUVOverlay(_phone->video_picture.bmp);
262 SDL_Rect rect;
263 rect.x = 0;
264 rect.y = 0;
265 rect.w = cs->video_decoder_ctx->width;
266 rect.h = cs->video_decoder_ctx->height;
267 SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect);
268 return 1;
269}
214 270
215 _audio_msg = rtp_recv_msg ( _rtp_audio ); 271int video_encoder_refresh(codec_state *cs, int bps)
216 _video_msg = rtp_recv_msg ( _rtp_video ); 272{
273 if (cs->video_encoder_ctx)
274 avcodec_close(cs->video_encoder_ctx);
275
276 cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC);
277
278 if (!cs->video_encoder) {
279 printf("init video_encoder failed\n");
280 return -1;
281 }
282
283 cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder);
284
285 if (!cs->video_encoder_ctx) {
286 printf("init video_encoder_ctx failed\n");
287 return -1;
288 }
289
290 cs->video_encoder_ctx->bit_rate = bps;
291 cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate;
292 av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0);
293 av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0);
294
295 cs->video_encoder_ctx->thread_count = 4;
296 cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95;
297 cs->video_encoder_ctx->rc_buffer_size = bps * 6;
298 cs->video_encoder_ctx->profile = 0;
299 cs->video_encoder_ctx->qmax = 54;
300 cs->video_encoder_ctx->qmin = 4;
301 AVRational myrational = {1, 25};
302 cs->video_encoder_ctx->time_base = myrational;
303 cs->video_encoder_ctx->gop_size = 99999;
304 cs->video_encoder_ctx->pix_fmt = PIX_FMT_YUV420P;
305 cs->video_encoder_ctx->width = cs->webcam_decoder_ctx->width;
306 cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height;
307
308 if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) {
309 printf("opening video encoder failed\n");
310 return -1;
311 }
312 return 0;
313}
217 314
218 if ( _audio_msg ) { 315int video_decoder_refresh(av_session_t* _phone, int width, int height)
219 /* Do whatever with msg 316{
220 printf("%d - %s\n", _audio_msg->header->sequnum, _audio_msg->data);*/ 317 printf("need to refresh\n");
221 rtp_free_msg ( _rtp_audio, _audio_msg ); 318 screen = SDL_SetVideoMode(width, height, 0, 0);
222 } 319
320 if (_phone->video_picture.bmp)
321 SDL_FreeYUVOverlay(_phone->video_picture.bmp);
322
323 _phone->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen);
324 _phone->sws_SDL_r_ctx = sws_getContext(width, height, _phone->cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P,
325 SWS_BILINEAR, NULL, NULL, NULL);
326 return 1;
327}
223 328
224 if ( _video_msg ) { 329void *encode_video_thread(void *arg)
225 /* Do whatever with msg 330{
226 p rintf("%d - %s\n", _video_msg->header->sequnum, _video_msg->data);*/ 331 av_session_t* _phone = arg;
227 rtp_free_msg ( _rtp_video, _video_msg ); 332
333 codec_state *cs = _phone->cs;
334 AVPacket pkt1, *packet = &pkt1;
335 int p = 0;
336 int got_packet;
337 int video_frame_finished;
338 AVFrame *s_video_frame;
339 AVFrame *webcam_frame;
340 s_video_frame = avcodec_alloc_frame();
341 webcam_frame = avcodec_alloc_frame();
342 AVPacket enc_video_packet;
343
344 uint8_t *buffer;
345 int numBytes;
346 /* Determine required buffer size and allocate buffer */
347 numBytes = avpicture_get_size(PIX_FMT_YUV420P, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height);
348 buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t),1);
349 avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, cs->webcam_decoder_ctx->width,
350 cs->webcam_decoder_ctx->height);
351 _phone->sws_ctx = sws_getContext(cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height,
352 cs->webcam_decoder_ctx->pix_fmt, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height, PIX_FMT_YUV420P,
353 SWS_BILINEAR, NULL, NULL, NULL);
354
355 while (!cs->quit && cs->send_video) {
356
357 if (av_read_frame(cs->video_format_ctx, packet) < 0) {
358 printf("error reading frame\n");
359
360 if (cs->video_format_ctx->pb->error != 0)
361 break;
362
363 continue;
228 } 364 }
365
366 if (packet->stream_index == cs->video_stream) {
367 if (avcodec_decode_video2(cs->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) {
368 printf("couldn't decode\n");
369 continue;
370 }
371
372 av_free_packet(packet);
373 sws_scale(_phone->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0,
374 cs->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize);
375 /* create a new I-frame every 60 frames */
376 ++p;
377
378 if (p == 60) {
379
380 s_video_frame->pict_type = AV_PICTURE_TYPE_BI ;
381 } else if (p == 61) {
382 s_video_frame->pict_type = AV_PICTURE_TYPE_I ;
383 p = 0;
384 } else {
385 s_video_frame->pict_type = AV_PICTURE_TYPE_P ;
386 }
387
388 if (video_frame_finished) {
389
390 if (avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet) < 0) {
391 printf("could not encode video frame\n");
392 continue;
393 }
394
395 if (!got_packet) {
396 continue;
397 }
398
399 if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n");
400
401 if ( 0 > rtp_send_msg ( _phone->_rtp_video, _phone->_messenger, enc_video_packet.data, enc_video_packet.size) ) {
402 printf("Failed sending message\n");
403 }
404
405 av_free_packet(&enc_video_packet);
406 }
407 } else {
408 av_free_packet(packet);
409 }
410 }
411
412 /* clean up codecs */
413 pthread_mutex_lock(&cs->avcodec_mutex_lock);
414 av_free(buffer);
415 av_free(webcam_frame);
416 av_free(s_video_frame);
417 sws_freeContext(_phone->sws_ctx);
418 avcodec_close(cs->webcam_decoder_ctx);
419 avcodec_close(cs->video_encoder_ctx);
420 pthread_mutex_unlock(&cs->avcodec_mutex_lock);
421 pthread_exit ( NULL );
422}
229 423
230 /* 424void *encode_audio_thread(void *arg)
231 * Send test message to the 'remote' 425{
232 */ 426 av_session_t* _phone = arg;
233 rtp_send_msg ( _rtp_audio, _messenger, (const uint8_t*)"audio\0", 6 ); 427
234 428 codec_state *cs = _phone->cs;
235 if ( _session->call->type_local == type_video ){ /* if local call send video */ 429 unsigned char encoded_data[4096];
236 rtp_send_msg ( _rtp_video, _messenger, (const uint8_t*)"video\0", 6 ); 430 int encoded_size = 0;
431 int16_t frame[4096];
432 int frame_size = AUDIO_FRAME_SIZE;
433 ALint sample = 0;
434 alcCaptureStart((ALCdevice*)_phone->audio_capture_device);
435
436 while (!cs->quit && cs->send_audio) {
437 alcGetIntegerv((ALCdevice*)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
438
439 if (sample >= frame_size) {
440 alcCaptureSamples((ALCdevice*)_phone->audio_capture_device, frame, frame_size);
441 encoded_size = opus_encode(cs->audio_encoder, frame, frame_size, encoded_data, 480);
442
443 if (encoded_size <= 0) {
444 printf("Could not encode audio packet\n");
445 } else {
446 rtp_send_msg ( _phone->_rtp_audio, _phone->_messenger, encoded_data, encoded_size );
447 }
448 } else {
449 usleep(1000);
237 } 450 }
451 }
452
453 /* clean up codecs */
454 pthread_mutex_lock(&cs->avcodec_mutex_lock);
455 alcCaptureStop((ALCdevice*)_phone->audio_capture_device);
456 alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device);
457
458 pthread_mutex_unlock(&cs->avcodec_mutex_lock);
459 pthread_exit ( NULL );
460}
238 461
239 _audio_msg = _video_msg = NULL; 462void *decode_video_thread(void *arg)
463{
464 av_session_t* _phone = arg;
465
466 codec_state *cs = _phone->cs;
467 cs->video_stream = 0;
468 RTPMessage *r_msg;
469 int dec_frame_finished;
470 AVFrame *r_video_frame;
471 r_video_frame = avcodec_alloc_frame();
472 AVPacket dec_video_packet;
473 av_new_packet (&dec_video_packet, 65536);
474 int width = 0;
475 int height = 0;
476
477 while (!cs->quit && cs->receive_video) {
478 r_msg = rtp_recv_msg ( _phone->_rtp_video );
240 479
480 if (r_msg) {
481 memcpy(dec_video_packet.data, r_msg->data, r_msg->length);
482 dec_video_packet.size = r_msg->length;
483 avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet);
484
485 if (dec_frame_finished) {
486 if (cs->video_decoder_ctx->width != width || cs->video_decoder_ctx->height != height) {
487 width = cs->video_decoder_ctx->width;
488 height = cs->video_decoder_ctx->height;
489 printf("w: %d h%d \n", width, height);
490 video_decoder_refresh(_phone, width, height);
491 }
492
493 display_received_frame(_phone, r_video_frame);
494 } else {
495 /* TODO: request the sender to create a new i-frame immediatly */
496 printf("Bad video packet\n");
497 }
498
499 rtp_free_msg(NULL, r_msg);
500 }
241 501
242 /* Send ~1k messages per second 502 usleep(1000);
243 * That _should_ be enough for both Audio and Video
244 */
245 usleep ( 1000 );
246 /* -------------------- */
247 } 503 }
248 504
249 if ( _audio_msg ) rtp_free_msg(_rtp_audio, _audio_msg); 505 printf("vend\n");
250 rtp_release_session_recv(_rtp_audio); 506 /* clean up codecs */
251 rtp_terminate_session(_rtp_audio, _messenger); 507 pthread_mutex_lock(&cs->avcodec_mutex_lock);
508 av_free(r_video_frame);
509 avcodec_close(cs->video_decoder_ctx);
510 pthread_mutex_unlock(&cs->avcodec_mutex_lock);
511 pthread_exit ( NULL );
512}
513
514void *decode_audio_thread(void *arg)
515{
516 av_session_t* _phone = arg;
252 517
253 if ( _video_msg ) rtp_free_msg(_rtp_video, _video_msg); 518 codec_state *cs = _phone->cs;
254 rtp_release_session_recv(_rtp_video); 519 RTPMessage *r_msg;
255 rtp_terminate_session(_rtp_video, _messenger);
256 520
257 INFO("Media thread finished!"); 521 int frame_size = AUDIO_FRAME_SIZE;
258 522 int data_size;
523
524 ALCdevice *dev;
525 ALCcontext *ctx;
526 ALuint source, *buffers;
527 dev = alcOpenDevice(NULL);
528 ctx = alcCreateContext(dev, NULL);
529 alcMakeContextCurrent(ctx);
530 int openal_buffers = 5;
531
532 buffers = calloc(sizeof(ALuint) * openal_buffers,1);
533 alGenBuffers(openal_buffers, buffers);
534 alGenSources((ALuint)1, &source);
535 alSourcei(source, AL_LOOPING, AL_FALSE);
536
537 ALuint buffer;
538 ALint val;
539
540 uint16_t zeros[frame_size];
541 memset(zeros, 0, frame_size);
542
543 int i;
544 for (i = 0; i < openal_buffers; ++i) {
545 alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000);
546 }
547
548 alSourceQueueBuffers(source, openal_buffers, buffers);
549 alSourcePlay(source);
550
551 if (alGetError() != AL_NO_ERROR) {
552 fprintf(stderr, "Error starting audio\n");
553 cs->quit = 1;
554 }
555
556 struct jitter_buffer *j_buf = NULL;
557
558 j_buf = create_queue(20);
559
560 int success = 0;
561
562 int dec_frame_len = 0;
563
564 opus_int16 PCM[frame_size];
565
566 while (!cs->quit && cs->receive_audio) {
567
568 r_msg = rtp_recv_msg ( _phone->_rtp_audio );
569
570 if (r_msg) {
571 /* push the packet into the queue */
572 queue(j_buf, r_msg);
573 }
574
575 /* grab a packet from the queue */
576 success = 0;
577 alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
578
579 if (val > 0)
580 r_msg = dequeue(j_buf, &success);
581
582 if (success > 0) {
583 /* good packet */
584 if (success == 1) {
585 dec_frame_len = opus_decode(cs->audio_decoder, r_msg->data, r_msg->length, PCM, frame_size, 0);
586 //rtp_free_msg(NULL, r_msg);
587 }
588
589 /* lost packet */
590 if (success == 2) {
591 printf("lost packet\n");
592 dec_frame_len = opus_decode(cs->audio_decoder, NULL, 0, PCM, frame_size, 1);
593 }
594
595 if (dec_frame_len > 0) {
596 alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
597
598 if (val <= 0)
599 continue;
600
601 alSourceUnqueueBuffers(source, 1, &buffer);
602 data_size = av_samples_get_buffer_size(NULL, 1, dec_frame_len, AV_SAMPLE_FMT_S16, 1);
603 alBufferData(buffer, AL_FORMAT_MONO16, PCM, data_size, 48000);
604 int error = alGetError();
605
606 if (error != AL_NO_ERROR) {
607 fprintf(stderr, "Error setting buffer %d\n", error);
608 break;
609 }
610
611 alSourceQueueBuffers(source, 1, &buffer);
612
613 if (alGetError() != AL_NO_ERROR) {
614 fprintf(stderr, "error: could not buffer audio\n");
615 break;
616 }
617
618 alGetSourcei(source, AL_SOURCE_STATE, &val);
619
620 if (val != AL_PLAYING)
621 alSourcePlay(source);
622
623
624 }
625 }
626
627 usleep(1000);
628 }
629
630 /* clean up codecs */
631 pthread_mutex_lock(&cs->avcodec_mutex_lock);
632
633 /* clean up openal */
634 alDeleteSources(1, &source);
635 alDeleteBuffers(openal_buffers, buffers);
636 alcMakeContextCurrent(NULL);
637 alcDestroyContext(ctx);
638 alcCloseDevice(dev);
639 pthread_mutex_unlock(&cs->avcodec_mutex_lock);
259 pthread_exit ( NULL ); 640 pthread_exit ( NULL );
260} 641}
261 642
643
644
645
646
262int phone_startmedia_loop ( av_session_t* _phone ) 647int phone_startmedia_loop ( av_session_t* _phone )
263{ 648{
264 if ( !_phone ){ 649 if ( !_phone ){
265 return -1; 650 return -1;
266 } 651 }
267 652
268 _phone->_rtp_audio = rtp_init_session ( 653 _phone->_rtp_audio = rtp_init_session (
269 type_audio, 654 type_audio,
270 _phone->_messenger, 655 _phone->_messenger,
271 _phone->_msi->call->peers[0], 656 _phone->_msi->call->peers[0],
272 _phone->_msi->call->key_peer, 657 _phone->_msi->call->key_peer,
273 _phone->_msi->call->key_local, 658 _phone->_msi->call->key_local,
274 _phone->_msi->call->nonce_peer, 659 _phone->_msi->call->nonce_peer,
275 _phone->_msi->call->nonce_local 660 _phone->_msi->call->nonce_local
276 ); 661 );
277 662
278 _phone->_rtp_audio = rtp_init_session ( 663 _phone->_rtp_audio = rtp_init_session (
279 type_video, 664 type_video,
280 _phone->_messenger, 665 _phone->_messenger,
281 _phone->_msi->call->peers[0], 666 _phone->_msi->call->peers[0],
282 _phone->_msi->call->key_peer, 667 _phone->_msi->call->key_peer,
283 _phone->_msi->call->key_local, 668 _phone->_msi->call->key_local,
284 _phone->_msi->call->nonce_peer, 669 _phone->_msi->call->nonce_peer,
285 _phone->_msi->call->nonce_local 670 _phone->_msi->call->nonce_local
286 ); 671 );
287 672
288 673 _phone->cs->quit = 0;
289 if ( 0 > event.rise(phone_handle_media_transport_poll, _phone) ) 674
675 init_encoder(_phone->cs);
676 init_decoder(_phone->cs);
677
678 /*
679 * Rise all threads
680 */
681
682 /* Only checks for last peer */
683 if ( _phone->_msi->call->type_peer[0] == type_video && 0 > event.rise(encode_video_thread, _phone) )
684 {
685 INFO("Error while starting encode_video_thread()");
686 return -1;
687 }
688
689 /* Always send audio */
690 if ( 0 > event.rise(encode_audio_thread, _phone) )
691 {
692 INFO("Error while starting encode_audio_thread()");
693 return -1;
694 }
695
696 if ( _phone->_msi->call->type_peer[0] == type_video && 0 > event.rise(decode_video_thread, _phone) )
697 {
698 INFO("Error while starting decode_video_thread()");
699 return -1;
700 }
701
702 if ( 0 > event.rise(decode_audio_thread, _phone) )
290 { 703 {
291 printf("Error while starting phone_handle_media_transport_poll()\n"); 704 INFO("Error while starting decode_audio_thread()");
292 return -1; 705 return -1;
293 } 706 }
294 else return 0; 707
708
709 return 0;
295} 710}
296 711
297 712
713
714
715
716
717/*********************************************
718 *********************************************
719 *********************************************
720 *********************************************
721 *********************************************
722 *********************************************
723 *********************************************
724 *********************************************
725 */
726
727
298/* Some example callbacks */ 728/* Some example callbacks */
299 729
300void* callback_recv_invite ( void* _arg ) 730void* callback_recv_invite ( void* _arg )
301{ 731{
302 const char* _call_type;
303
304 MSISession* _msi = _arg; 732 MSISession* _msi = _arg;
305 733
306 switch ( _msi->call->type_peer[_msi->call->peer_count - 1] ){ 734 switch ( _msi->call->type_peer[_msi->call->peer_count - 1] ){
307 case type_audio: 735 case type_audio:
308 _call_type = "audio"; 736 INFO( "Incoming audio call!");
309 break; 737 break;
310 case type_video: 738 case type_video:
311 _call_type = "video"; 739 INFO( "Incoming video call!");
312 break; 740 break;
313 } 741 }
314 742
315 INFO( "Incoming %s call!", _call_type ); 743 pthread_exit(NULL);
316
317} 744}
318void* callback_recv_ringing ( void* _arg ) 745void* callback_recv_ringing ( void* _arg )
319{ 746{
320 INFO ( "Ringing!" ); 747 INFO ( "Ringing!" );
748 pthread_exit(NULL);
321} 749}
322void* callback_recv_starting ( void* _arg ) 750void* callback_recv_starting ( void* _arg )
323{ 751{
@@ -327,10 +755,22 @@ void* callback_recv_starting ( void* _arg )
327 } else { 755 } else {
328 INFO ("Call started! ( press h to hangup )"); 756 INFO ("Call started! ( press h to hangup )");
329 } 757 }
758 pthread_exit(NULL);
330} 759}
331void* callback_recv_ending ( void* _arg ) 760void* callback_recv_ending ( void* _arg )
332{ 761{
762 av_session_t* _phone = ((MSISession*)_arg)->agent_handler;
763
764 _phone->cs->send_audio = 0;
765 _phone->cs->send_video = 0;
766 _phone->cs->receive_audio = 0;
767 _phone->cs->receive_video = 0;
768
769 /* Wait until all threads are done */
770 usleep(10000000);
771
333 INFO ( "Call ended!" ); 772 INFO ( "Call ended!" );
773 pthread_exit(NULL);
334} 774}
335 775
336void* callback_recv_error ( void* _arg ) 776void* callback_recv_error ( void* _arg )
@@ -338,6 +778,7 @@ void* callback_recv_error ( void* _arg )
338 MSISession* _session = _arg; 778 MSISession* _session = _arg;
339 779
340 INFO( "Error: %s", _session->last_error_str ); 780 INFO( "Error: %s", _session->last_error_str );
781 pthread_exit(NULL);
341} 782}
342 783
343void* callback_call_started ( void* _arg ) 784void* callback_call_started ( void* _arg )
@@ -348,43 +789,45 @@ void* callback_call_started ( void* _arg )
348 } else { 789 } else {
349 INFO ("Call started! ( press h to hangup )"); 790 INFO ("Call started! ( press h to hangup )");
350 } 791 }
351 792
793 pthread_exit(NULL);
352} 794}
353void* callback_call_canceled ( void* _arg ) 795void* callback_call_canceled ( void* _arg )
354{ 796{
355 INFO ( "Call canceled!" ); 797 INFO ( "Call canceled!" );
798 pthread_exit(NULL);
356} 799}
357void* callback_call_rejected ( void* _arg ) 800void* callback_call_rejected ( void* _arg )
358{ 801{
359 INFO ( "Call rejected!" ); 802 INFO ( "Call rejected!" );
803 pthread_exit(NULL);
360} 804}
361void* callback_call_ended ( void* _arg ) 805void* callback_call_ended ( void* _arg )
362{ 806{
807 av_session_t* _phone = ((MSISession*)_arg)->agent_handler;
808
809 _phone->cs->send_audio = 0;
810 _phone->cs->send_video = 0;
811 _phone->cs->receive_audio = 0;
812 _phone->cs->receive_video = 0;
813
814 /* Wait until all threads are done */
815 usleep(10000000);
816
363 INFO ( "Call ended!" ); 817 INFO ( "Call ended!" );
818 pthread_exit(NULL);
364} 819}
365 820
366void* callback_requ_timeout ( void* _arg ) 821void* callback_requ_timeout ( void* _arg )
367{ 822{
368 INFO( "No answer! " ); 823 INFO( "No answer! " );
369} 824 pthread_exit(NULL);
370
371int av_connect_to_dht(av_session_t* _phone, char* _dht_key, const char* _dht_addr, unsigned short _dht_port)
372{
373 unsigned char *_binary_string = hex_string_to_bin(_dht_key);
374
375 uint16_t _port = htons(_dht_port);
376
377 int _if = tox_bootstrap_from_address(_phone->_messenger, _dht_addr, 1, _port, _binary_string );
378
379 free(_binary_string);
380
381 return _if ? 0 : -1;
382} 825}
383 826
384av_session_t* av_init_session() 827av_session_t* av_init_session()
385{ 828{
386 av_session_t* _retu = malloc(sizeof(av_session_t)); 829 av_session_t* _retu = malloc(sizeof(av_session_t));
387 830
388 /* Initialize our mutex */ 831 /* Initialize our mutex */
389 pthread_mutex_init ( &_retu->_mutex, NULL ); 832 pthread_mutex_init ( &_retu->_mutex, NULL );
390 833
@@ -400,13 +843,61 @@ av_session_t* av_init_session()
400 _retu->_rtp_audio = NULL; 843 _retu->_rtp_audio = NULL;
401 _retu->_rtp_video = NULL; 844 _retu->_rtp_video = NULL;
402 845
846
847 const ALchar *_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
848 int i = 0;
849 const ALchar *device_names[20];
850
851 if ( _device_list ) {
852 INFO("\nAvailable Capture Devices are:");
853
854 while (*_device_list ) {
855 device_names[i] = _device_list;
856 INFO("%d) %s", i, device_names[i]);
857 _device_list += strlen( _device_list ) + 1;
858 ++i;
859 }
860 }
861
862 INFO("Enter capture device number");
863
864 char dev[2]; char* left;
865 fgets(dev, 2, stdin);
866 long selection = strtol(dev, &left, 10);
867
868 if ( *left ) {
869 printf("'%s' is not a number!", dev);
870 fflush(stdout);
871 exit(EXIT_FAILURE);
872 }
873 else {
874 INFO("Selected: %d ( %s )", selection, device_names[selection]);
875 }
876
877 _retu->cs = av_calloc(sizeof(codec_state), 1);
878
879 _retu->audio_capture_device =
880 (struct ALCdevice*)alcCaptureOpenDevice(
881 device_names[selection], AUDIO_SAMPLE_RATE, AL_FORMAT_MONO16, AUDIO_FRAME_SIZE * 4);
882
883
884 if (alcGetError((ALCdevice*)_retu->audio_capture_device) != AL_NO_ERROR) {
885 printf("Could not start capture device! %d\n", alcGetError((ALCdevice*)_retu->audio_capture_device));
886 return 0;
887 }
888
889
890 init_encoder(_retu->cs);
891 init_decoder(_retu->cs);
892
893
403 uint8_t _byte_address[TOX_FRIEND_ADDRESS_SIZE]; 894 uint8_t _byte_address[TOX_FRIEND_ADDRESS_SIZE];
404 tox_get_address(_retu->_messenger, _byte_address ); 895 tox_get_address(_retu->_messenger, _byte_address );
405 fraddr_to_str( _byte_address, _retu->_my_public_id ); 896 fraddr_to_str( _byte_address, _retu->_my_public_id );
406 897
407 898
408 /* Initialize msi */ 899 /* Initialize msi */
409 _retu->_msi = msi_init_session ( _retu->_messenger, _USERAGENT ); 900 _retu->_msi = msi_init_session ( _retu->_messenger, (const uint8_t*)_USERAGENT );
410 901
411 if ( !_retu->_msi ) { 902 if ( !_retu->_msi ) {
412 fprintf ( stderr, "msi_init_session() failed\n" ); 903 fprintf ( stderr, "msi_init_session() failed\n" );
@@ -498,6 +989,20 @@ int av_add_friend(av_session_t* _phone, char* _friend_hash)
498 989
499 return _number; 990 return _number;
500} 991}
992
993int av_connect_to_dht(av_session_t* _phone, char* _dht_key, const char* _dht_addr, unsigned short _dht_port)
994{
995 unsigned char *_binary_string = hex_string_to_bin(_dht_key);
996
997 uint16_t _port = htons(_dht_port);
998
999 int _if = tox_bootstrap_from_address(_phone->_messenger, _dht_addr, 1, _port, _binary_string );
1000
1001 free(_binary_string);
1002
1003 return _if ? 0 : -1;
1004}
1005
501/*********************************/ 1006/*********************************/
502 1007
503void do_phone ( av_session_t* _phone ) 1008void do_phone ( av_session_t* _phone )
@@ -512,7 +1017,7 @@ void do_phone ( av_session_t* _phone )
512 "q (quit)\n" 1017 "q (quit)\n"
513 "================================================================================" 1018 "================================================================================"
514 ); 1019 );
515 1020
516 while ( 1 ) 1021 while ( 1 )
517 { 1022 {
518 char _line [ 1500 ]; 1023 char _line [ 1500 ];
@@ -613,6 +1118,9 @@ void do_phone ( av_session_t* _phone )
613 INFO("Quitting!"); 1118 INFO("Quitting!");
614 return; 1119 return;
615 } 1120 }
1121 case '\n':
1122 {
1123 }
616 default: 1124 default:
617 { 1125 {
618 INFO("Invalid command!"); 1126 INFO("Invalid command!");
@@ -670,6 +1178,7 @@ int print_help ( const char* _name )
670 "\t[IP] (DHT ip)\n" 1178 "\t[IP] (DHT ip)\n"
671 "\t[PORT] (DHT port)\n" 1179 "\t[PORT] (DHT port)\n"
672 "\t[KEY] (DHT public key)\n" 1180 "\t[KEY] (DHT public key)\n"
1181 "P.S. Friends and key are stored in ./tox_phone.conf\n"
673 ,_name ); 1182 ,_name );
674 return 1; 1183 return 1;
675} 1184}
@@ -681,13 +1190,12 @@ int main ( int argc, char* argv [] )
681 1190
682 char* _convertable; 1191 char* _convertable;
683 1192
684 int _wait_seconds = 5;
685 1193
686 const char* _ip = argv[1]; 1194 const char* _ip = argv[1];
687 char* _key = argv[3]; 1195 char* _key = argv[3];
688 unsigned short _port = strtol(argv[2], &_convertable, 10); 1196 unsigned short _port = strtol(argv[2], &_convertable, 10);
689 1197
690 if ( *_convertable ){ 1198 if ( *_convertable ) {
691 printf("Invalid port: cannot convert string to long: %s", _convertable); 1199 printf("Invalid port: cannot convert string to long: %s", _convertable);
692 return 1; 1200 return 1;
693 } 1201 }
@@ -697,7 +1205,6 @@ int main ( int argc, char* argv [] )
697 tox_callback_friend_request(_phone->_messenger, av_friend_requ, _phone); 1205 tox_callback_friend_request(_phone->_messenger, av_friend_requ, _phone);
698 tox_callback_status_message(_phone->_messenger, av_friend_active, _phone); 1206 tox_callback_status_message(_phone->_messenger, av_friend_active, _phone);
699 1207
700 system("clear");
701 1208
702 INFO("\r================================================================================\n" 1209 INFO("\r================================================================================\n"
703 "[!] Trying dht@%s:%d" 1210 "[!] Trying dht@%s:%d"
@@ -711,6 +1218,7 @@ int main ( int argc, char* argv [] )
711 fflush(stdout); 1218 fflush(stdout);
712 1219
713 int _r; 1220 int _r;
1221 int _wait_seconds = 5;
714 for ( _r = 0; _r == 0; _r = av_wait_dht(_phone, _wait_seconds, _ip, _key, _port) ) _wait_seconds --; 1222 for ( _r = 0; _r == 0; _r = av_wait_dht(_phone, _wait_seconds, _ip, _key, _port) ) _wait_seconds --;
715 1223
716 1224