summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
Diffstat (limited to 'toxav')
-rwxr-xr-xtoxav/phone.c704
-rw-r--r--toxav/toxmedia.c473
-rw-r--r--toxav/toxmedia.h99
-rwxr-xr-xtoxav/toxmsi.c237
-rwxr-xr-xtoxav/toxmsi.h4
-rwxr-xr-xtoxav/toxrtp.c275
-rwxr-xr-xtoxav/toxrtp.h7
7 files changed, 943 insertions, 856 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
diff --git a/toxav/toxmedia.c b/toxav/toxmedia.c
index aff3cf8c..359832d3 100644
--- a/toxav/toxmedia.c
+++ b/toxav/toxmedia.c
@@ -34,45 +34,13 @@
34#include <libswscale/swscale.h> 34#include <libswscale/swscale.h>
35#include <libavdevice/avdevice.h> 35#include <libavdevice/avdevice.h>
36#include <libavutil/opt.h> 36#include <libavutil/opt.h>
37#include <AL/al.h>
38#include <AL/alc.h>
39#include <SDL/SDL.h>
40#include <SDL/SDL_thread.h>
41#include <pthread.h>
42#include <opus/opus.h> 37#include <opus/opus.h>
38#include <assert.h>
43 39
44#include "toxmsi.h" 40#include "toxmsi.h"
45#include "toxrtp.h" 41#include "toxrtp.h"
46#include "toxmedia.h" 42#include "toxmedia.h"
47 43
48SDL_Surface *screen;
49
50int display_received_frame(codec_state *cs, AVFrame *r_video_frame)
51{
52 AVPicture pict;
53 SDL_LockYUVOverlay(cs->video_picture.bmp);
54
55 pict.data[0] = cs->video_picture.bmp->pixels[0];
56 pict.data[1] = cs->video_picture.bmp->pixels[2];
57 pict.data[2] = cs->video_picture.bmp->pixels[1];
58 pict.linesize[0] = cs->video_picture.bmp->pitches[0];
59 pict.linesize[1] = cs->video_picture.bmp->pitches[2];
60 pict.linesize[2] = cs->video_picture.bmp->pitches[1];
61
62 /* Convert the image into YUV format that SDL uses */
63 sws_scale(cs->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0,
64 cs->video_decoder_ctx->height, pict.data, pict.linesize );
65
66 SDL_UnlockYUVOverlay(cs->video_picture.bmp);
67 SDL_Rect rect;
68 rect.x = 0;
69 rect.y = 0;
70 rect.w = cs->video_decoder_ctx->width;
71 rect.h = cs->video_decoder_ctx->height;
72 SDL_DisplayYUVOverlay(cs->video_picture.bmp, &rect);
73 return 1;
74}
75
76struct jitter_buffer { 44struct jitter_buffer {
77 RTPMessage **queue; 45 RTPMessage **queue;
78 uint16_t capacity; 46 uint16_t capacity;
@@ -85,6 +53,7 @@ struct jitter_buffer {
85 uint8_t id_set; 53 uint8_t id_set;
86}; 54};
87 55
56
88struct jitter_buffer *create_queue(int capacity) 57struct jitter_buffer *create_queue(int capacity)
89{ 58{
90 struct jitter_buffer *q; 59 struct jitter_buffer *q;
@@ -240,10 +209,23 @@ int queue(struct jitter_buffer *q, RTPMessage *pk)
240 209
241int init_receive_audio(codec_state *cs) 210int init_receive_audio(codec_state *cs)
242{ 211{
243 int err = OPUS_OK; 212 int rc;
244 cs->audio_decoder = opus_decoder_create(48000, 1, &err); 213 cs->audio_decoder = opus_decoder_create(48000, 1, &rc );
245 opus_decoder_init(cs->audio_decoder, 48000, 1); 214
246 printf("init audio decoder successful\n"); 215 if ( rc != OPUS_OK ){
216 printf("Error while starting audio decoder!\n");
217 return 0;
218 }
219
220 rc = opus_decoder_init(cs->audio_decoder, 48000, 1);
221
222 if ( rc != OPUS_OK ){
223 printf("Error while starting audio decoder!\n");
224 return 0;
225 }
226
227
228 printf("Init audio decoder successful\n");
247 return 1; 229 return 1;
248} 230}
249 231
@@ -252,23 +234,23 @@ int init_receive_video(codec_state *cs)
252 cs->video_decoder = avcodec_find_decoder(VIDEO_CODEC); 234 cs->video_decoder = avcodec_find_decoder(VIDEO_CODEC);
253 235
254 if (!cs->video_decoder) { 236 if (!cs->video_decoder) {
255 printf("init video_decoder failed\n"); 237 printf("Init video_decoder failed\n");
256 return 0; 238 return 0;
257 } 239 }
258 240
259 cs->video_decoder_ctx = avcodec_alloc_context3(cs->video_decoder); 241 cs->video_decoder_ctx = avcodec_alloc_context3(cs->video_decoder);
260 242
261 if (!cs->video_decoder_ctx) { 243 if (!cs->video_decoder_ctx) {
262 printf("init video_decoder_ctx failed\n"); 244 printf("Init video_decoder_ctx failed\n");
263 return 0; 245 return 0;
264 } 246 }
265 247
266 if (avcodec_open2(cs->video_decoder_ctx, cs->video_decoder, NULL) < 0) { 248 if (avcodec_open2(cs->video_decoder_ctx, cs->video_decoder, NULL) < 0) {
267 printf("opening video decoder failed\n"); 249 printf("Opening video decoder failed\n");
268 return 0; 250 return 0;
269 } 251 }
270 252
271 printf("init video decoder successful\n"); 253 printf("Init video decoder successful\n");
272 return 1; 254 return 1;
273} 255}
274 256
@@ -356,32 +338,6 @@ int init_send_audio(codec_state *cs)
356{ 338{
357 cs->support_send_audio = 0; 339 cs->support_send_audio = 0;
358 340
359 const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
360 int i = 0;
361 const ALchar *device_names[20];
362
363 if (pDeviceList) {
364 printf("\nAvailable Capture Devices are:\n");
365
366 while (*pDeviceList) {
367 device_names[i] = pDeviceList;
368 printf("%d) %s\n", i, device_names[i]);
369 pDeviceList += strlen(pDeviceList) + 1;
370 ++i;
371 }
372 }
373
374 printf("enter capture device number: \n");
375 char dev[2];
376 fgets(dev, sizeof(dev), stdin);
377 cs->audio_capture_device = alcCaptureOpenDevice(device_names[dev[0] - 48], AUDIO_SAMPLE_RATE, AL_FORMAT_MONO16,
378 AUDIO_FRAME_SIZE * 4);
379
380 if (alcGetError(cs->audio_capture_device) != AL_NO_ERROR) {
381 printf("could not start capture device! %d\n", alcGetError(cs->audio_capture_device));
382 return 0;
383 }
384
385 int err = OPUS_OK; 341 int err = OPUS_OK;
386 cs->audio_bitrate = AUDIO_BITRATE; 342 cs->audio_bitrate = AUDIO_BITRATE;
387 cs->audio_encoder = opus_encoder_create(AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, &err); 343 cs->audio_encoder = opus_encoder_create(AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, &err);
@@ -435,385 +391,4 @@ int init_decoder(codec_state *cs)
435 cs->receive_video = 1; 391 cs->receive_video = 1;
436 392
437 return 1; 393 return 1;
438} 394} \ No newline at end of file
439
440int video_encoder_refresh(codec_state *cs, int bps)
441{
442 if (cs->video_encoder_ctx)
443 avcodec_close(cs->video_encoder_ctx);
444
445 cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC);
446
447 if (!cs->video_encoder) {
448 printf("init video_encoder failed\n");
449 return -1;
450 }
451
452 cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder);
453
454 if (!cs->video_encoder_ctx) {
455 printf("init video_encoder_ctx failed\n");
456 return -1;
457 }
458
459 cs->video_encoder_ctx->bit_rate = bps;
460 cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate;
461 av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0);
462 av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0);
463
464 cs->video_encoder_ctx->thread_count = 4;
465 cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95;
466 cs->video_encoder_ctx->rc_buffer_size = bps * 6;
467 cs->video_encoder_ctx->profile = 0;
468 cs->video_encoder_ctx->qmax = 54;
469 cs->video_encoder_ctx->qmin = 4;
470 AVRational myrational = {1, 25};
471 cs->video_encoder_ctx->time_base = myrational;
472 cs->video_encoder_ctx->gop_size = 99999;
473 cs->video_encoder_ctx->pix_fmt = PIX_FMT_YUV420P;
474 cs->video_encoder_ctx->width = cs->webcam_decoder_ctx->width;
475 cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height;
476
477 if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) {
478 printf("opening video encoder failed\n");
479 return -1;
480 }
481 return 0;
482}
483
484void *encode_video_thread(void *arg)
485{
486 codec_state *cs = (codec_state *)arg;
487 AVPacket pkt1, *packet = &pkt1;
488 int p = 0;
489 int err;
490 int got_packet;
491 RTPMessage *s_video_msg;
492 int video_frame_finished;
493 AVFrame *s_video_frame;
494 AVFrame *webcam_frame;
495 s_video_frame = avcodec_alloc_frame();
496 webcam_frame = avcodec_alloc_frame();
497 AVPacket enc_video_packet;
498
499 uint8_t *buffer;
500 int numBytes;
501 /* Determine required buffer size and allocate buffer */
502 numBytes = avpicture_get_size(PIX_FMT_YUV420P, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height);
503 buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t),1);
504 avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, cs->webcam_decoder_ctx->width,
505 cs->webcam_decoder_ctx->height);
506 cs->sws_ctx = sws_getContext(cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height,
507 cs->webcam_decoder_ctx->pix_fmt, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height, PIX_FMT_YUV420P,
508 SWS_BILINEAR, NULL, NULL, NULL);
509
510 while (!cs->quit && cs->send_video) {
511
512 if (av_read_frame(cs->video_format_ctx, packet) < 0) {
513 printf("error reading frame\n");
514
515 if (cs->video_format_ctx->pb->error != 0)
516 break;
517
518 continue;
519 }
520
521 if (packet->stream_index == cs->video_stream) {
522 if (avcodec_decode_video2(cs->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) {
523 printf("couldn't decode\n");
524 continue;
525 }
526
527 av_free_packet(packet);
528 sws_scale(cs->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0,
529 cs->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize);
530 /* create a new I-frame every 60 frames */
531 ++p;
532
533 if (p == 60) {
534
535 s_video_frame->pict_type = AV_PICTURE_TYPE_BI ;
536 } else if (p == 61) {
537 s_video_frame->pict_type = AV_PICTURE_TYPE_I ;
538 p = 0;
539 } else {
540 s_video_frame->pict_type = AV_PICTURE_TYPE_P ;
541 }
542
543 if (video_frame_finished) {
544 err = avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet);
545
546 if (err < 0) {
547 printf("could not encode video frame\n");
548 continue;
549 }
550
551 if (!got_packet) {
552 continue;
553 }
554
555 pthread_mutex_lock(&cs->rtp_msg_mutex_lock);
556
557 if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n");
558
559 if ( 0 > rtp_send_msg ( cs->_rtp_video, cs->_messenger, enc_video_packet.data, enc_video_packet.size) ) {
560 printf("invalid message\n");
561 }
562
563 pthread_mutex_unlock(&cs->rtp_msg_mutex_lock);
564 av_free_packet(&enc_video_packet);
565 }
566 } else {
567 av_free_packet(packet);
568 }
569 }
570
571 /* clean up codecs */
572 pthread_mutex_lock(&cs->avcodec_mutex_lock);
573 av_free(buffer);
574 av_free(webcam_frame);
575 av_free(s_video_frame);
576 sws_freeContext(cs->sws_ctx);
577 avcodec_close(cs->webcam_decoder_ctx);
578 avcodec_close(cs->video_encoder_ctx);
579 pthread_mutex_unlock(&cs->avcodec_mutex_lock);
580 pthread_exit ( NULL );
581}
582
583void *encode_audio_thread(void *arg)
584{
585 codec_state *cs = (codec_state *)arg;
586 RTPMessage *s_audio_msg;
587 unsigned char encoded_data[4096];
588 int encoded_size = 0;
589 int16_t frame[4096];
590 int frame_size = AUDIO_FRAME_SIZE;
591 ALint sample = 0;
592 alcCaptureStart(cs->audio_capture_device);
593
594 while (!cs->quit && cs->send_audio) {
595 alcGetIntegerv(cs->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
596
597 if (sample >= frame_size) {
598 alcCaptureSamples(cs->audio_capture_device, frame, frame_size);
599 encoded_size = opus_encode(cs->audio_encoder, frame, frame_size, encoded_data, 480);
600
601 if (encoded_size <= 0) {
602 printf("Could not encode audio packet\n");
603 } else {
604 pthread_mutex_lock(&cs->rtp_msg_mutex_lock);
605
606 rtp_send_msg ( cs->_rtp_audio, cs->_messenger, encoded_data, encoded_size );
607
608 pthread_mutex_unlock(&cs->rtp_msg_mutex_lock);
609
610 }
611 } else {
612 usleep(1000);
613 }
614 }
615
616 /* clean up codecs */
617 pthread_mutex_lock(&cs->avcodec_mutex_lock);
618 alcCaptureStop(cs->audio_capture_device);
619 alcCaptureCloseDevice(cs->audio_capture_device);
620
621 pthread_mutex_unlock(&cs->avcodec_mutex_lock);
622 pthread_exit ( NULL );
623}
624
625
626int video_decoder_refresh(codec_state *cs, int width, int height)
627{
628 printf("need to refresh\n");
629 screen = SDL_SetVideoMode(width, height, 0, 0);
630
631 if (cs->video_picture.bmp)
632 SDL_FreeYUVOverlay(cs->video_picture.bmp);
633
634 cs->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen);
635 cs->sws_SDL_r_ctx = sws_getContext(width, height, cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P,
636 SWS_BILINEAR, NULL, NULL, NULL);
637 return 1;
638}
639
640void *decode_video_thread(void *arg)
641{
642 codec_state *cs = (codec_state *)arg;
643 cs->video_stream = 0;
644 RTPMessage *r_msg;
645 int dec_frame_finished;
646 AVFrame *r_video_frame;
647 r_video_frame = avcodec_alloc_frame();
648 AVPacket dec_video_packet;
649 av_new_packet (&dec_video_packet, 65536);
650 int width = 0;
651 int height = 0;
652
653 while (!cs->quit && cs->receive_video) {
654 r_msg = rtp_recv_msg ( cs->_rtp_video );
655
656 if (r_msg) {
657 memcpy(dec_video_packet.data, r_msg->data, r_msg->length);
658 dec_video_packet.size = r_msg->length;
659 avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet);
660
661 if (dec_frame_finished) {
662 if (cs->video_decoder_ctx->width != width || cs->video_decoder_ctx->height != height) {
663 width = cs->video_decoder_ctx->width;
664 height = cs->video_decoder_ctx->height;
665 printf("w: %d h%d \n", width, height);
666 video_decoder_refresh(cs, width, height);
667 }
668
669 display_received_frame(cs, r_video_frame);
670 } else {
671 /* TODO: request the sender to create a new i-frame immediatly */
672 printf("bad video packet\n");
673 }
674
675 rtp_free_msg(cs->_rtp_video, r_msg);
676 }
677
678 usleep(1000);
679 }
680
681 printf("vend\n");
682 /* clean up codecs */
683 pthread_mutex_lock(&cs->avcodec_mutex_lock);
684 av_free(r_video_frame);
685 avcodec_close(cs->video_decoder_ctx);
686 pthread_mutex_unlock(&cs->avcodec_mutex_lock);
687 pthread_exit ( NULL );
688}
689
690void *decode_audio_thread(void *arg)
691{
692 codec_state *cs = (codec_state *)arg;
693 RTPMessage *r_msg;
694
695 int frame_size = AUDIO_FRAME_SIZE;
696 int data_size;
697
698 ALCdevice *dev;
699 ALCcontext *ctx;
700 ALuint source, *buffers;
701 dev = alcOpenDevice(NULL);
702 ctx = alcCreateContext(dev, NULL);
703 alcMakeContextCurrent(ctx);
704 int openal_buffers = 5;
705
706 buffers = calloc(sizeof(ALuint) * openal_buffers,1);
707 alGenBuffers(openal_buffers, buffers);
708 alGenSources((ALuint)1, &source);
709 alSourcei(source, AL_LOOPING, AL_FALSE);
710
711 ALuint buffer;
712 ALint val;
713
714 ALenum error;
715 uint16_t zeros[frame_size];
716 int i;
717
718 for (i = 0; i < frame_size; i++) {
719 zeros[i] = 0;
720 }
721
722 for (i = 0; i < openal_buffers; ++i) {
723 alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000);
724 }
725
726 alSourceQueueBuffers(source, openal_buffers, buffers);
727 alSourcePlay(source);
728
729 if (alGetError() != AL_NO_ERROR) {
730 fprintf(stderr, "Error starting audio\n");
731 cs->quit = 1;
732 }
733
734 struct jitter_buffer *j_buf = NULL;
735
736 j_buf = create_queue(20);
737
738 int success = 0;
739
740 int dec_frame_len;
741
742 opus_int16 PCM[frame_size];
743
744 while (!cs->quit && cs->receive_audio) {
745
746 r_msg = rtp_recv_msg ( cs->_rtp_audio );
747
748 if (r_msg) {
749 /* push the packet into the queue */
750 queue(j_buf, r_msg);
751 }
752
753 /* grab a packet from the queue */
754 success = 0;
755 alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
756
757 if (val > 0)
758 r_msg = dequeue(j_buf, &success);
759
760 if (success > 0) {
761 /* good packet */
762 if (success == 1) {
763 dec_frame_len = opus_decode(cs->audio_decoder, r_msg->data, r_msg->length, PCM, frame_size, 0);
764 rtp_free_msg(cs->_rtp_audio, r_msg);
765 }
766
767 /* lost packet */
768 if (success == 2) {
769 printf("lost packet\n");
770 dec_frame_len = opus_decode(cs->audio_decoder, NULL, 0, PCM, frame_size, 1);
771 }
772
773 if (dec_frame_len > 0) {
774 alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
775
776 if (val <= 0)
777 continue;
778
779 alSourceUnqueueBuffers(source, 1, &buffer);
780 data_size = av_samples_get_buffer_size(NULL, 1, dec_frame_len, AV_SAMPLE_FMT_S16, 1);
781 alBufferData(buffer, AL_FORMAT_MONO16, PCM, data_size, 48000);
782 int error = alGetError();
783
784 if (error != AL_NO_ERROR) {
785 fprintf(stderr, "Error setting buffer %d\n", error);
786 break;
787 }
788
789 alSourceQueueBuffers(source, 1, &buffer);
790
791 if (alGetError() != AL_NO_ERROR) {
792 fprintf(stderr, "error: could not buffer audio\n");
793 break;
794 }
795
796 alGetSourcei(source, AL_SOURCE_STATE, &val);
797
798 if (val != AL_PLAYING)
799 alSourcePlay(source);
800
801
802 }
803 }
804
805 usleep(1000);
806 }
807
808 /* clean up codecs */
809 pthread_mutex_lock(&cs->avcodec_mutex_lock);
810
811 /* clean up openal */
812 alDeleteSources(1, &source);
813 alDeleteBuffers(openal_buffers, buffers);
814 alcMakeContextCurrent(NULL);
815 alcDestroyContext(ctx);
816 alcCloseDevice(dev);
817 pthread_mutex_unlock(&cs->avcodec_mutex_lock);
818 pthread_exit ( NULL );
819}
diff --git a/toxav/toxmedia.h b/toxav/toxmedia.h
index aad299bb..927c5ef8 100644
--- a/toxav/toxmedia.h
+++ b/toxav/toxmedia.h
@@ -27,25 +27,25 @@
27 27
28#include <stdio.h> 28#include <stdio.h>
29#include <math.h> 29#include <math.h>
30#include "toxrtp.h"
31#include "toxmsi.h"
32#include "../toxcore/tox.h"
33
34/* Video encoding/decoding */
30#include <libavcodec/avcodec.h> 35#include <libavcodec/avcodec.h>
31#include <libavformat/avformat.h> 36#include <libavformat/avformat.h>
32#include <libswscale/swscale.h> 37#include <libswscale/swscale.h>
33#include <libavdevice/avdevice.h> 38#include <libavdevice/avdevice.h>
34#include <libavutil/opt.h> 39#include <libavutil/opt.h>
35#include <pthread.h>
36#include <AL/al.h>
37#include <AL/alc.h>
38#include "toxrtp.h"
39#include "tox.h"
40 40
41#include <SDL/SDL.h> 41/* Audio encoding/decoding */
42#include <opus/opus.h> 42#include <opus/opus.h>
43 43
44/* ffmpeg VP8 codec ID */ 44/* ffmpeg VP8 codec ID */
45#define VIDEO_CODEC AV_CODEC_ID_VP8 45#define VIDEO_CODEC AV_CODEC_ID_VP8
46 46
47/* ffmpeg Opus codec ID */ 47/* ffmpeg Opus codec ID */
48#define AUDIO_CODEC AV_CODEC_ID_OPUS 48#define AUDIO_CODEC AV_CODEC_ID_OPUS
49 49
50/* default video bitrate in bytes/s */ 50/* default video bitrate in bytes/s */
51#define VIDEO_BITRATE 10*1000 51#define VIDEO_BITRATE 10*1000
@@ -75,14 +75,6 @@
75#define DEFAULT_WEBCAM "0" 75#define DEFAULT_WEBCAM "0"
76#endif 76#endif
77 77
78extern SDL_Surface *screen;
79
80typedef struct {
81 SDL_Overlay *bmp;
82 int width, height;
83} VideoPicture;
84
85
86typedef struct { 78typedef struct {
87 uint8_t send_audio; 79 uint8_t send_audio;
88 uint8_t receive_audio; 80 uint8_t receive_audio;
@@ -95,71 +87,46 @@ typedef struct {
95 uint8_t support_receive_video; 87 uint8_t support_receive_video;
96 88
97 /* video encoding */ 89 /* video encoding */
98 AVInputFormat *video_input_format; 90 AVInputFormat *video_input_format;
99 AVFormatContext *video_format_ctx; 91 AVFormatContext *video_format_ctx;
100 uint8_t video_stream; 92 uint8_t video_stream;
101 AVCodecContext *webcam_decoder_ctx; 93 AVCodecContext *webcam_decoder_ctx;
102 AVCodec *webcam_decoder; 94 AVCodec *webcam_decoder;
103 AVCodecContext *video_encoder_ctx; 95 AVCodecContext *video_encoder_ctx;
104 AVCodec *video_encoder; 96 AVCodec *video_encoder;
105 97
106 /* video decoding */ 98 /* video decoding */
107 AVCodecContext *video_decoder_ctx; 99 AVCodecContext *video_decoder_ctx;
108 AVCodec *video_decoder; 100 AVCodec *video_decoder;
109 101
110 /* audio encoding */ 102 /* audio encoding */
111 ALCdevice *audio_capture_device; 103 OpusEncoder *audio_encoder;
112 OpusEncoder *audio_encoder; 104 int audio_bitrate;
113 int audio_bitrate;
114 105
115 /* audio decoding */ 106 /* audio decoding */
116 OpusDecoder *audio_decoder; 107 OpusDecoder *audio_decoder;
117 108
118 uint8_t req_video_refresh; 109 uint8_t req_video_refresh;
119
120 /* context for converting image format to something SDL can use*/
121 struct SwsContext *sws_SDL_r_ctx;
122
123 /* context for converting webcam image format to something the video encoder can use */
124 struct SwsContext *sws_ctx;
125
126 /* rendered video picture, ready for display */
127 VideoPicture video_picture;
128
129 RTPSession *_rtp_video;
130 RTPSession *_rtp_audio;
131
132 Tox* _messenger;
133 110
134 pthread_t encode_audio_thread;
135 pthread_t encode_video_thread;
136
137 pthread_t decode_audio_thread;
138 pthread_t decode_video_thread;
139
140 pthread_mutex_t rtp_msg_mutex_lock; 111 pthread_mutex_t rtp_msg_mutex_lock;
141 pthread_mutex_t avcodec_mutex_lock; 112 pthread_mutex_t avcodec_mutex_lock;
113
114 uint8_t quit;
115
116 uint32_t frame_rate;
142 117
143 uint8_t quit; 118} codec_state;
144 SDL_Event SDL_event;
145 119
146 MSISession *_msi;
147 uint32_t _frame_rate;
148 120
149} codec_state; 121struct jitter_buffer *create_queue(int capacity);
122int empty_queue(struct jitter_buffer *q);
123
124int queue(struct jitter_buffer *q, RTPMessage *pk);
125RTPMessage *dequeue(struct jitter_buffer *q, int *success);
126
150 127
151int display_received_frame(codec_state *cs, AVFrame *r_video_frame);
152int init_receive_audio(codec_state *cs);
153int init_decoder(codec_state *cs);
154int init_send_video(codec_state *cs);
155int init_send_audio(codec_state *cs);
156int init_encoder(codec_state *cs); 128int init_encoder(codec_state *cs);
157int video_encoder_refresh(codec_state *cs, int bps); 129int init_decoder(codec_state *cs);
158void *encode_video_thread(void *arg); 130
159void *encode_audio_thread(void *arg);
160int video_decoder_refresh(codec_state *cs, int width, int height);
161int handle_rtp_video_packet(codec_state *cs, RTPMessage *r_msg);
162void *decode_video_thread(void *arg);
163void *decode_audio_thread(void *arg);
164 131
165#endif 132#endif
diff --git a/toxav/toxmsi.c b/toxav/toxmsi.c
index cf0914ab..d504838a 100755
--- a/toxav/toxmsi.c
+++ b/toxav/toxmsi.c
@@ -119,7 +119,7 @@ typedef struct _MSIMessage {
119 119
120 120
121 121
122static MSICallback callbacks[9] = {0}; 122static MSICallback callbacks[10] = {0};
123 123
124 124
125/* define strings for the identifiers */ 125/* define strings for the identifiers */
@@ -330,10 +330,10 @@ MSIMessage* msi_new_message ( uint8_t type, const uint8_t* type_id ) {
330 memset ( _retu, 0, sizeof ( MSIMessage ) ); 330 memset ( _retu, 0, sizeof ( MSIMessage ) );
331 331
332 if ( type == TYPE_REQUEST ) { 332 if ( type == TYPE_REQUEST ) {
333 ALLOCATE_HEADER ( _retu->request, type_id, strlen ( type_id ) ) 333 ALLOCATE_HEADER ( _retu->request, type_id, strlen ( (const char*)type_id ) )
334 334
335 } else if ( type == TYPE_RESPONSE ) { 335 } else if ( type == TYPE_RESPONSE ) {
336 ALLOCATE_HEADER ( _retu->response, type_id, strlen ( type_id ) ) 336 ALLOCATE_HEADER ( _retu->response, type_id, strlen ( (const char*)type_id ) )
337 337
338 } else { 338 } else {
339 free_message ( _retu ); 339 free_message ( _retu );
@@ -507,7 +507,7 @@ void t_randomstr ( uint8_t* str, size_t size ) {
507 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 507 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
508 "abcdefghijklmnopqrstuvwxyz"; 508 "abcdefghijklmnopqrstuvwxyz";
509 509
510 int _it = 0; 510 size_t _it = 0;
511 511
512 for ( ; _it < size; _it++ ) { 512 for ( ; _it < size; _it++ ) {
513 str[_it] = _bytes[ randombytes_random() % 61 ]; 513 str[_it] = _bytes[ randombytes_random() % 61 ];
@@ -523,7 +523,7 @@ typedef enum {
523 error_no_call, /* no call in session */ 523 error_no_call, /* no call in session */
524 error_no_crypto_key, /* no crypto key */ 524 error_no_crypto_key, /* no crypto key */
525 525
526 error_busy, 526 error_busy
527 527
528} MSICallError; /* Error codes */ 528} MSICallError; /* Error codes */
529 529
@@ -675,15 +675,18 @@ void* handle_timeout ( void* arg )
675 /* Send hangup either way */ 675 /* Send hangup either way */
676 MSISession* _session = arg; 676 MSISession* _session = arg;
677 677
678 uint32_t* _peers = _session->call->peers; 678 if ( _session && _session->call ) {
679 uint16_t _peer_count = _session->call->peer_count; 679
680 680 uint32_t* _peers = _session->call->peers;
681 681 uint16_t _peer_count = _session->call->peer_count;
682 /* Cancel all? */ 682
683 uint16_t _it = 0; 683
684 for ( ; _it < _peer_count; _it++ ) 684 /* Cancel all? */
685 msi_cancel ( arg, _peers[_it] ); 685 uint16_t _it = 0;
686 686 for ( ; _it < _peer_count; _it++ )
687 msi_cancel ( arg, _peers[_it] );
688
689 }
687 690
688 ( *callbacks[cb_timeout] ) ( arg ); 691 ( *callbacks[cb_timeout] ) ( arg );
689 ( *callbacks[cb_ending ] ) ( arg ); 692 ( *callbacks[cb_ending ] ) ( arg );
@@ -714,107 +717,6 @@ void add_peer( MSICall* call, int peer_id )
714 717
715 718
716/** 719/**
717 * @brief BASIC call flow:
718 *
719 * ALICE BOB
720 * | invite --> |
721 * | |
722 * | <-- ringing |
723 * | |
724 * | <-- starting |
725 * | |
726 * | start --> |
727 * | |
728 * | <-- MEDIA TRANS --> |
729 * | |
730 * | end --> |
731 * | |
732 * | <-- ending |
733 *
734 * Alice calls Bob by sending invite packet.
735 * Bob recvs the packet and sends an ringing packet;
736 * which notifies Alice that her invite is acknowledged.
737 * Ringing screen shown on both sides.
738 * Bob accepts the invite for a call by sending starting packet.
739 * Alice recvs the starting packet and sends the started packet to
740 * inform Bob that she recved the starting packet.
741 * Now the media transmission is established ( i.e. RTP transmission ).
742 * Alice hangs up and sends end packet.
743 * Bob recves the end packet and sends ending packet
744 * as the acknowledgement that the call is ending.
745 *
746 *
747 */
748void msi_handle_packet ( Messenger* messenger, int source, uint8_t* data, uint16_t length, void* object )
749{
750 MSISession* _session = object;
751 MSIMessage* _msg;
752
753 _msg = parse_message ( data );
754
755 if ( !_msg ) return;
756
757 _msg->friend_id = source;
758
759
760 /* Now handle message */
761
762 if ( _msg->request.header_value ) { /* Handle request */
763
764 const uint8_t* _request_value = _msg->request.header_value;
765
766 if ( same ( _request_value, stringify_request ( invite ) ) ) {
767 handle_recv_invite ( _session, _msg );
768
769 } else if ( same ( _request_value, stringify_request ( start ) ) ) {
770 handle_recv_start ( _session, _msg );
771
772 } else if ( same ( _request_value, stringify_request ( cancel ) ) ) {
773 handle_recv_cancel ( _session, _msg );
774
775 } else if ( same ( _request_value, stringify_request ( reject ) ) ) {
776 handle_recv_reject ( _session, _msg );
777
778 } else if ( same ( _request_value, stringify_request ( end ) ) ) {
779 handle_recv_end ( _session, _msg );
780 }
781
782 else {
783 free_message ( _msg );
784 return;
785 }
786
787 } else if ( _msg->response.header_value ) { /* Handle response */
788
789 const uint8_t* _response_value = _msg->response.header_value;
790
791 if ( same ( _response_value, stringify_response ( ringing ) ) ) {
792 handle_recv_ringing ( _session, _msg );
793
794 } else if ( same ( _response_value, stringify_response ( starting ) ) ) {
795 handle_recv_starting ( _session, _msg );
796
797 } else if ( same ( _response_value, stringify_response ( ending ) ) ) {
798 handle_recv_ending ( _session, _msg );
799
800 } else if ( same ( _response_value, stringify_response ( error ) ) ) {
801 handle_recv_error ( _session, _msg );
802 } else {
803 free_message ( _msg );
804 return;
805 }
806
807 /* Got response so cancel timer */
808 if ( _session->call )
809 event.timer_release ( _session->call->request_timer_id );
810
811 }
812
813 free_message ( _msg );
814}
815
816
817/**
818 * @brief Speaks for it self. 720 * @brief Speaks for it self.
819 * 721 *
820 * @param session Control session. 722 * @param session Control session.
@@ -1076,6 +978,111 @@ int handle_recv_error ( MSISession* session, MSIMessage* msg ) {
1076} 978}
1077 979
1078 980
981/**
982 * @brief BASIC call flow:
983 *
984 * ALICE BOB
985 * | invite --> |
986 * | |
987 * | <-- ringing |
988 * | |
989 * | <-- starting |
990 * | |
991 * | start --> |
992 * | |
993 * | <-- MEDIA TRANS --> |
994 * | |
995 * | end --> |
996 * | |
997 * | <-- ending |
998 *
999 * Alice calls Bob by sending invite packet.
1000 * Bob recvs the packet and sends an ringing packet;
1001 * which notifies Alice that her invite is acknowledged.
1002 * Ringing screen shown on both sides.
1003 * Bob accepts the invite for a call by sending starting packet.
1004 * Alice recvs the starting packet and sends the started packet to
1005 * inform Bob that she recved the starting packet.
1006 * Now the media transmission is established ( i.e. RTP transmission ).
1007 * Alice hangs up and sends end packet.
1008 * Bob recves the end packet and sends ending packet
1009 * as the acknowledgement that the call is ending.
1010 *
1011 *
1012 */
1013void msi_handle_packet ( Messenger* messenger, int source, uint8_t* data, uint16_t length, void* object )
1014{
1015 /* Unused */
1016 (void)messenger;
1017 (void)&length;
1018
1019 MSISession* _session = object;
1020 MSIMessage* _msg;
1021
1022 _msg = parse_message ( data );
1023
1024 if ( !_msg ) return;
1025
1026 _msg->friend_id = source;
1027
1028
1029 /* Now handle message */
1030
1031 if ( _msg->request.header_value ) { /* Handle request */
1032
1033 const uint8_t* _request_value = _msg->request.header_value;
1034
1035 if ( same ( _request_value, stringify_request ( invite ) ) ) {
1036 handle_recv_invite ( _session, _msg );
1037
1038 } else if ( same ( _request_value, stringify_request ( start ) ) ) {
1039 handle_recv_start ( _session, _msg );
1040
1041 } else if ( same ( _request_value, stringify_request ( cancel ) ) ) {
1042 handle_recv_cancel ( _session, _msg );
1043
1044 } else if ( same ( _request_value, stringify_request ( reject ) ) ) {
1045 handle_recv_reject ( _session, _msg );
1046
1047 } else if ( same ( _request_value, stringify_request ( end ) ) ) {
1048 handle_recv_end ( _session, _msg );
1049 }
1050
1051 else {
1052 free_message ( _msg );
1053 return;
1054 }
1055
1056 } else if ( _msg->response.header_value ) { /* Handle response */
1057
1058 const uint8_t* _response_value = _msg->response.header_value;
1059
1060 if ( same ( _response_value, stringify_response ( ringing ) ) ) {
1061 handle_recv_ringing ( _session, _msg );
1062
1063 } else if ( same ( _response_value, stringify_response ( starting ) ) ) {
1064 handle_recv_starting ( _session, _msg );
1065
1066 } else if ( same ( _response_value, stringify_response ( ending ) ) ) {
1067 handle_recv_ending ( _session, _msg );
1068
1069 } else if ( same ( _response_value, stringify_response ( error ) ) ) {
1070 handle_recv_error ( _session, _msg );
1071 } else {
1072 free_message ( _msg );
1073 return;
1074 }
1075
1076 /* Got response so cancel timer */
1077 if ( _session->call )
1078 event.timer_release ( _session->call->request_timer_id );
1079
1080 }
1081
1082 free_message ( _msg );
1083}
1084
1085
1079/******************************************************************************************************************** 1086/********************************************************************************************************************
1080 * ******************************************************************************************************************* 1087 * *******************************************************************************************************************
1081 ******************************************************************************************************************** 1088 ********************************************************************************************************************
diff --git a/toxav/toxmsi.h b/toxav/toxmsi.h
index c45662a6..63cff9e5 100755
--- a/toxav/toxmsi.h
+++ b/toxav/toxmsi.h
@@ -41,7 +41,7 @@ typedef void* ( *MSICallback ) ( void* arg );
41 */ 41 */
42typedef enum { 42typedef enum {
43 type_audio = 70, 43 type_audio = 70,
44 type_video, 44 type_video
45} MSICallType; 45} MSICallType;
46 46
47 47
@@ -133,7 +133,7 @@ typedef enum {
133 133
134 /* Protocol */ 134 /* Protocol */
135 cb_error, 135 cb_error,
136 cb_timeout, 136 cb_timeout
137 137
138} MSICallbackID; 138} MSICallbackID;
139 139
diff --git a/toxav/toxrtp.c b/toxav/toxrtp.c
index 03d20363..6b5ded45 100755
--- a/toxav/toxrtp.c
+++ b/toxav/toxrtp.c
@@ -28,8 +28,7 @@
28 28
29#include "toxrtp.h" 29#include "toxrtp.h"
30#include <assert.h> 30#include <assert.h>
31#include <limits.h> 31#include <stdlib.h>
32#include <pthread.h>
33 32
34#include "../toxcore/util.h" 33#include "../toxcore/util.h"
35#include "../toxcore/network.h" 34#include "../toxcore/network.h"
@@ -59,6 +58,88 @@
59#define GET_SETTING_PAYLOAD(_h) ((_h->marker_payloadt) & 0x7f) 58#define GET_SETTING_PAYLOAD(_h) ((_h->marker_payloadt) & 0x7f)
60 59
61 60
61/**
62 * @brief Converts 4 bytes to uint32_t
63 *
64 * @param dest Where to convert
65 * @param bytes What bytes
66 * @return void
67 */
68inline__ void bytes_to_U32(uint32_t* dest, const uint8_t* bytes)
69{
70 *dest =
71#ifdef WORDS_BIGENDIAN
72 ( ( uint32_t ) * bytes ) |
73 ( ( uint32_t ) * ( bytes + 1 ) << 8 ) |
74 ( ( uint32_t ) * ( bytes + 2 ) << 16 ) |
75 ( ( uint32_t ) * ( bytes + 3 ) << 24 ) ;
76#else
77 ( ( uint32_t ) * bytes << 24 ) |
78 ( ( uint32_t ) * ( bytes + 1 ) << 16 ) |
79 ( ( uint32_t ) * ( bytes + 2 ) << 8 ) |
80 ( ( uint32_t ) * ( bytes + 3 ) ) ;
81#endif
82}
83
84/**
85 * @brief Converts 2 bytes to uint16_t
86 *
87 * @param dest Where to convert
88 * @param bytes What bytes
89 * @return void
90 */
91inline__ void bytes_to_U16(uint16_t* dest, const uint8_t* bytes)
92{
93 *dest =
94#ifdef WORDS_BIGENDIAN
95 ( ( uint16_t ) * bytes ) |
96 ( ( uint16_t ) * ( bytes + 1 ) << 8 );
97#else
98 ( ( uint16_t ) * bytes << 8 ) |
99 ( ( uint16_t ) * ( bytes + 1 ) );
100#endif
101}
102
103/**
104 * @brief Convert uint32_t to byte string of size 4
105 *
106 * @param dest Where to convert
107 * @param value The value
108 * @return void
109 */
110inline__ void U32_to_bytes(uint8_t* dest, uint32_t value)
111{
112#ifdef WORDS_BIGENDIAN
113 *(dest) = ( value );
114 *(dest + 1) = ( value >> 8 );
115 *(dest + 2) = ( value >> 16 );
116 *(dest + 3) = ( value >> 24 );
117#else
118 *(dest) = ( value >> 24 );
119 *(dest + 1) = ( value >> 16 );
120 *(dest + 2) = ( value >> 8 );
121 *(dest + 3) = ( value );
122#endif
123}
124
125/**
126 * @brief Convert uint16_t to byte string of size 2
127 *
128 * @param dest Where to convert
129 * @param value The value
130 * @return void
131 */
132inline__ void U16_to_bytes(uint8_t* dest, uint16_t value)
133{
134#ifdef WORDS_BIGENDIAN
135 *(dest) = ( value );
136 *(dest + 1) = ( value >> 8 );
137#else
138 *(dest) = ( value >> 8 );
139 *(dest + 1) = ( value );
140#endif
141}
142
62 143
63/** 144/**
64 * @brief Checks if message came in late. 145 * @brief Checks if message came in late.
@@ -89,25 +170,31 @@ inline__ int check_late_message (RTPSession* session, RTPMessage* msg)
89 */ 170 */
90inline__ void increase_nonce(uint8_t* nonce, uint16_t target) 171inline__ void increase_nonce(uint8_t* nonce, uint16_t target)
91{ 172{
92 uint16_t _nonce_counter = ((uint16_t)( 173 uint16_t _nonce_counter;
93 (((uint16_t) nonce [crypto_box_NONCEBYTES - 1]) << 8 ) | 174
94 (((uint16_t) nonce [crypto_box_NONCEBYTES - 2]) ))); 175 uint8_t _reverse_bytes[2];
95 176 _reverse_bytes[0] = nonce[crypto_box_NONCEBYTES - 1];
177 _reverse_bytes[1] = nonce[crypto_box_NONCEBYTES - 2];
178
179 bytes_to_U16(&_nonce_counter, _reverse_bytes );
180
96 /* Check overflow */ 181 /* Check overflow */
97 if (_nonce_counter > USHRT_MAX - target ) { /* 2 bytes are not long enough */ 182 if (_nonce_counter > UINT16_MAX - target ) { /* 2 bytes are not long enough */
98 int _it = 3; 183 uint8_t _it = 3;
99 while ( _it <= crypto_box_NONCEBYTES ) _it += ++nonce[crypto_box_NONCEBYTES - _it] ? crypto_box_NONCEBYTES : 1; 184 while ( _it <= crypto_box_NONCEBYTES ) _it += ++nonce[crypto_box_NONCEBYTES - _it] ? crypto_box_NONCEBYTES : 1;
100 185
101 _nonce_counter = _nonce_counter - (USHRT_MAX - target ); /* Assign the rest of it */ 186 _nonce_counter = _nonce_counter - (UINT16_MAX - target ); /* Assign the rest of it */
102 } else { /* Increase nonce */ 187 } else { /* Increase nonce */
103 188
104 _nonce_counter+= target; 189 _nonce_counter+= target;
105 } 190 }
106 191
107 /* Assign the 8 last bytes */ 192 /* Assign the last bytes */
193
194 U16_to_bytes( _reverse_bytes, _nonce_counter);
195 nonce [crypto_box_NONCEBYTES - 1] = _reverse_bytes[0];
196 nonce [crypto_box_NONCEBYTES - 2] = _reverse_bytes[1];
108 197
109 nonce [crypto_box_NONCEBYTES - 1] = (uint8_t) (_nonce_counter >> 8);
110 nonce [crypto_box_NONCEBYTES - 2] = (uint8_t) (_nonce_counter);
111} 198}
112 199
113 200
@@ -141,15 +228,15 @@ static const uint32_t payload_table[] =
141 * @return RTPHeader* Extracted header. 228 * @return RTPHeader* Extracted header.
142 * @retval NULL Error occurred while extracting header. 229 * @retval NULL Error occurred while extracting header.
143 */ 230 */
144RTPHeader* extract_header ( const uint8_t* payload, size_t length ) 231RTPHeader* extract_header ( const uint8_t* payload, int length )
145{ 232{
146 if ( !payload ) { 233 if ( !payload || !length ) {
147 return NULL; 234 return NULL;
148 } 235 }
149 236
150 const uint8_t* _it = payload; 237 const uint8_t* _it = payload;
151 238
152 RTPHeader* _retu = calloc(sizeof(RTPHeader), 1); 239 RTPHeader* _retu = calloc(1, sizeof (RTPHeader));
153 assert(_retu); 240 assert(_retu);
154 241
155 _retu->flags = *_it; ++_it; 242 _retu->flags = *_it; ++_it;
@@ -168,7 +255,7 @@ RTPHeader* extract_header ( const uint8_t* payload, size_t length )
168 * Added a check for the size of the header little sooner so 255 * Added a check for the size of the header little sooner so
169 * I don't need to parse the other stuff if it's bad 256 * I don't need to parse the other stuff if it's bad
170 */ 257 */
171 uint8_t _cc = GET_FLAG_CSRCC ( _retu ); 258 uint8_t _cc = GET_FLAG_CSRCC ( _retu );
172 uint32_t _length = 12 /* Minimum header len */ + ( _cc * 4 ); 259 uint32_t _length = 12 /* Minimum header len */ + ( _cc * 4 );
173 260
174 if ( length < _length ) { 261 if ( length < _length ) {
@@ -178,7 +265,7 @@ RTPHeader* extract_header ( const uint8_t* payload, size_t length )
178 } 265 }
179 266
180 if ( _cc > 0 ) { 267 if ( _cc > 0 ) {
181 _retu->csrc = calloc ( sizeof ( uint32_t ), _cc ); 268 _retu->csrc = calloc (_cc, sizeof (uint32_t));
182 assert(_retu->csrc); 269 assert(_retu->csrc);
183 270
184 } else { /* But this should not happen ever */ 271 } else { /* But this should not happen ever */
@@ -191,26 +278,13 @@ RTPHeader* extract_header ( const uint8_t* payload, size_t length )
191 _retu->marker_payloadt = *_it; ++_it; 278 _retu->marker_payloadt = *_it; ++_it;
192 _retu->length = _length; 279 _retu->length = _length;
193 280
194 _retu->timestamp = ( ( uint32_t ) * _it << 24 ) |
195 ( ( uint32_t ) * ( _it + 1 ) << 16 ) |
196 ( ( uint32_t ) * ( _it + 2 ) << 8 ) |
197 ( * ( _it + 3 ) ) ;
198 281
199 _it += 4; 282 bytes_to_U32(&_retu->timestamp, _it); _it += 4;
283 bytes_to_U32(&_retu->ssrc, _it);
200 284
201 _retu->ssrc = ( ( uint32_t ) * _it << 24 ) | 285 uint8_t _x;
202 ( ( uint32_t ) * ( _it + 1 ) << 16 ) |
203 ( ( uint32_t ) * ( _it + 2 ) << 8 ) |
204 ( ( uint32_t ) * ( _it + 3 ) ) ;
205
206
207 size_t _x;
208 for ( _x = 0; _x < _cc; _x++ ) { 286 for ( _x = 0; _x < _cc; _x++ ) {
209 _it += 4; 287 _it += 4; bytes_to_U32(&(_retu->csrc[_x]), _it);
210 _retu->csrc[_x] = ( ( uint32_t ) * _it << 24 ) |
211 ( ( uint32_t ) * ( _it + 1 ) << 16 ) |
212 ( ( uint32_t ) * ( _it + 2 ) << 8 ) |
213 ( ( uint32_t ) * ( _it + 3 ) ) ;
214 } 288 }
215 289
216 return _retu; 290 return _retu;
@@ -228,29 +302,26 @@ RTPExtHeader* extract_ext_header ( const uint8_t* payload, size_t length )
228{ 302{
229 const uint8_t* _it = payload; 303 const uint8_t* _it = payload;
230 304
231 RTPExtHeader* _retu = calloc(sizeof(RTPExtHeader), 1); 305 RTPExtHeader* _retu = calloc(1, sizeof (RTPExtHeader));
232 assert(_retu); 306 assert(_retu);
233 307
234 uint16_t _ext_length = ( ( uint16_t ) * _it << 8 ) | * ( _it + 1 ); _it += 2; 308 uint16_t _ext_length;
309 bytes_to_U16(&_ext_length, _it); _it += 2;
310
235 311
236 if ( length < ( _ext_length * sizeof(uint32_t) ) ) { 312 if ( length < ( _ext_length * sizeof(uint32_t) ) ) {
237 return NULL; 313 return NULL;
238 } 314 }
239 315
240 _retu->length = _ext_length; 316 _retu->length = _ext_length;
241 _retu->type = ( ( uint16_t ) * _it << 8 ) | * ( _it + 1 ); _it -= 2; 317 bytes_to_U16(&_retu->type, _it); _it += 2;
242 318
243 _retu->table = calloc(sizeof(uint32_t), _ext_length ); 319 _retu->table = calloc(_ext_length, sizeof (uint32_t));
244 assert(_retu->table); 320 assert(_retu->table);
245 321
246 uint32_t* _table = _retu->table; 322 uint16_t _x;
247 size_t _i; 323 for ( _x = 0; _x < _ext_length; _x++ ) {
248 for ( _i = 0; _i < _ext_length; _i++ ) { 324 _it += 4; bytes_to_U32(&(_retu->table[_x]), _it);
249 _it += 4;
250 _table[_i] = ( ( uint32_t ) * _it << 24 ) |
251 ( ( uint32_t ) * ( _it + 1 ) << 16 ) |
252 ( ( uint32_t ) * ( _it + 2 ) << 8 ) |
253 ( ( uint32_t ) * ( _it + 3 ) ) ;
254 } 325 }
255 326
256 return _retu; 327 return _retu;
@@ -271,33 +342,18 @@ uint8_t* add_header ( RTPHeader* header, uint8_t* payload )
271 342
272 343
273 /* Add sequence number first */ 344 /* Add sequence number first */
274 *_it = ( header->sequnum >> 8 ); ++_it; 345 U16_to_bytes(_it, header->sequnum); _it += 2;
275 *_it = ( header->sequnum ); ++_it;
276 346
277 *_it = header->flags; ++_it; 347 *_it = header->flags; ++_it;
278 *_it = header->marker_payloadt; ++_it; 348 *_it = header->marker_payloadt; ++_it;
279 349
280 350
281 uint32_t _timestamp = header->timestamp; 351 U32_to_bytes( _it, header->timestamp); _it+=4;
282 *_it = ( _timestamp >> 24 ); ++_it; 352 U32_to_bytes( _it, header->ssrc);
283 *_it = ( _timestamp >> 16 ); ++_it; 353
284 *_it = ( _timestamp >> 8 ); ++_it; 354 uint8_t _x;
285 *_it = ( _timestamp ); ++_it;
286
287 uint32_t _ssrc = header->ssrc;
288 *_it = ( _ssrc >> 24 ); ++_it;
289 *_it = ( _ssrc >> 16 ); ++_it;
290 *_it = ( _ssrc >> 8 ); ++_it;
291 *_it = ( _ssrc );
292
293 uint32_t *_csrc = header->csrc;
294 size_t _x;
295 for ( _x = 0; _x < _cc; _x++ ) { 355 for ( _x = 0; _x < _cc; _x++ ) {
296 ++_it; 356 _it+=4; U32_to_bytes( _it, header->csrc[_x]);
297 *_it = ( _csrc[_x] >> 24 ); ++_it;
298 *_it = ( _csrc[_x] >> 16 ); ++_it;
299 *_it = ( _csrc[_x] >> 8 ); ++_it;
300 *_it = ( _csrc[_x] );
301 } 357 }
302 358
303 return _it; 359 return _it;
@@ -314,21 +370,12 @@ uint8_t* add_ext_header ( RTPExtHeader* header, uint8_t* payload )
314{ 370{
315 uint8_t* _it = payload; 371 uint8_t* _it = payload;
316 372
317 *_it = ( header->length >> 8 ); _it++; 373 U16_to_bytes(_it, header->length); _it+=2;
318 *_it = ( header->length ); _it++; 374 U16_to_bytes(_it, header->type); _it-=2; /* Return to 0 position */
319 375
320 *_it = ( header->type >> 8 ); ++_it; 376 uint16_t _x;
321 *_it = ( header->type ); 377 for ( _x = 0; _x < header->length; _x++ ) {
322 378 _it+=4; U32_to_bytes(_it, header->table[_x]);
323 size_t x;
324
325 uint32_t* _hd_ext = header->table;
326 for ( x = 0; x < header->length; x++ ) {
327 ++_it;
328 *_it = ( _hd_ext[x] >> 24 ); ++_it;
329 *_it = ( _hd_ext[x] >> 16 ); ++_it;
330 *_it = ( _hd_ext[x] >> 8 ); ++_it;
331 *_it = ( _hd_ext[x] );
332 } 379 }
333 380
334 return _it; 381 return _it;
@@ -342,8 +389,7 @@ uint8_t* add_ext_header ( RTPExtHeader* header, uint8_t* payload )
342 */ 389 */
343RTPHeader* build_header ( RTPSession* session ) 390RTPHeader* build_header ( RTPSession* session )
344{ 391{
345 RTPHeader* _retu; 392 RTPHeader* _retu = calloc ( 1, sizeof (RTPHeader) );
346 _retu = calloc ( sizeof * _retu, 1 );
347 assert(_retu); 393 assert(_retu);
348 394
349 ADD_FLAG_VERSION ( _retu, session->version ); 395 ADD_FLAG_VERSION ( _retu, session->version );
@@ -358,7 +404,7 @@ RTPHeader* build_header ( RTPSession* session )
358 _retu->ssrc = session->ssrc; 404 _retu->ssrc = session->ssrc;
359 405
360 if ( session->cc > 0 ) { 406 if ( session->cc > 0 ) {
361 _retu->csrc = calloc(sizeof(uint32_t), session->cc); 407 _retu->csrc = calloc(session->cc, sizeof (uint32_t));
362 assert(_retu->csrc); 408 assert(_retu->csrc);
363 409
364 int i; 410 int i;
@@ -388,12 +434,9 @@ RTPHeader* build_header ( RTPSession* session )
388 * @return RTPMessage* 434 * @return RTPMessage*
389 * @retval NULL Error occurred. 435 * @retval NULL Error occurred.
390 */ 436 */
391RTPMessage* msg_parse ( RTPSession* session, uint16_t sequnum, const uint8_t* data, uint32_t length ) 437RTPMessage* msg_parse ( uint16_t sequnum, const uint8_t* data, int length )
392{ 438{
393 assert( length != -1); 439 RTPMessage* _retu = calloc(1, sizeof (RTPMessage));
394
395 RTPMessage* _retu = calloc(sizeof(RTPMessage), 1);
396 assert(_retu);
397 440
398 _retu->header = extract_header ( data, length ); /* It allocates memory and all */ 441 _retu->header = extract_header ( data, length ); /* It allocates memory and all */
399 442
@@ -413,7 +456,7 @@ RTPMessage* msg_parse ( RTPSession* session, uint16_t sequnum, const uint8_t* da
413 if ( _retu->ext_header ){ 456 if ( _retu->ext_header ){
414 _retu->length -= ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); 457 _retu->length -= ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 );
415 _from_pos += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); 458 _from_pos += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 );
416 } else { 459 } else { /* Error */
417 free (_retu->ext_header); 460 free (_retu->ext_header);
418 free (_retu->header); 461 free (_retu->header);
419 free (_retu); 462 free (_retu);
@@ -423,20 +466,9 @@ RTPMessage* msg_parse ( RTPSession* session, uint16_t sequnum, const uint8_t* da
423 _retu->ext_header = NULL; 466 _retu->ext_header = NULL;
424 } 467 }
425 468
426 /* Get the payload */
427 _retu->data = calloc ( sizeof ( uint8_t ), _retu->length );
428 assert(_retu->data);
429
430 memcpy ( _retu->data, data + _from_pos, length - _from_pos ); 469 memcpy ( _retu->data, data + _from_pos, length - _from_pos );
431
432 _retu->next = NULL; 470 _retu->next = NULL;
433 471
434
435 if ( session && check_late_message ( session, _retu) < 0 ){
436 session->rsequnum = _retu->header->sequnum;
437 session->timestamp = _retu->header->timestamp;
438 }
439
440 return _retu; 472 return _retu;
441} 473}
442 474
@@ -460,8 +492,9 @@ int rtp_handle_packet ( void* object, IP_Port ip_port, uint8_t* data, uint32_t l
460 return -1; 492 return -1;
461 493
462 uint8_t _plain[MAX_UDP_PACKET_SIZE]; 494 uint8_t _plain[MAX_UDP_PACKET_SIZE];
463 495
464 uint16_t _sequnum = ( ( uint16_t ) data[1] << 8 ) | data[2]; 496 uint16_t _sequnum;
497 bytes_to_U16(&_sequnum, data + 1);
465 498
466 /* Clculate the right nonce */ 499 /* Clculate the right nonce */
467 uint8_t _calculated[crypto_box_NONCEBYTES]; 500 uint8_t _calculated[crypto_box_NONCEBYTES];
@@ -500,10 +533,9 @@ int rtp_handle_packet ( void* object, IP_Port ip_port, uint8_t* data, uint32_t l
500 } 533 }
501 } 534 }
502 535
503 _msg = msg_parse ( NULL, _sequnum, _plain, _decrypted_length ); 536 _msg = msg_parse ( _sequnum, _plain, _decrypted_length );
504 537
505 if ( !_msg ) 538 if ( !_msg ) return -1;
506 return -1;
507 539
508 /* Hopefully this goes well 540 /* Hopefully this goes well
509 * NOTE: Is this even used? 541 * NOTE: Is this even used?
@@ -548,7 +580,7 @@ RTPMessage* rtp_new_message ( RTPSession* session, const uint8_t* data, uint32_t
548 return NULL; 580 return NULL;
549 581
550 uint8_t* _from_pos; 582 uint8_t* _from_pos;
551 RTPMessage* _retu = calloc(sizeof(RTPMessage), 1); 583 RTPMessage* _retu = calloc(1, sizeof (RTPMessage));
552 assert(_retu); 584 assert(_retu);
553 585
554 /* Sets header values and copies the extension header in _retu */ 586 /* Sets header values and copies the extension header in _retu */
@@ -560,17 +592,10 @@ RTPMessage* rtp_new_message ( RTPSession* session, const uint8_t* data, uint32_t
560 592
561 if ( _retu->ext_header ) { 593 if ( _retu->ext_header ) {
562 _total_length += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); 594 _total_length += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 );
563 /* Allocate Memory for _retu->_data */
564 _retu->data = calloc ( sizeof _retu->data, _total_length );
565 assert(_retu->data);
566 595
567 _from_pos = add_header ( _retu->header, _retu->data ); 596 _from_pos = add_header ( _retu->header, _retu->data );
568 _from_pos = add_ext_header ( _retu->ext_header, _from_pos + 1 ); 597 _from_pos = add_ext_header ( _retu->ext_header, _from_pos + 1 );
569 } else { 598 } else {
570 /* Allocate Memory for _retu->_data */
571 _retu->data = calloc ( sizeof _retu->data, _total_length );
572 assert(_retu->data);
573
574 _from_pos = add_header ( _retu->header, _retu->data ); 599 _from_pos = add_header ( _retu->header, _retu->data );
575 } 600 }
576 601
@@ -590,6 +615,11 @@ RTPMessage* rtp_new_message ( RTPSession* session, const uint8_t* data, uint32_t
590} 615}
591 616
592 617
618
619
620
621
622
593/******************************************************************************************************************** 623/********************************************************************************************************************
594 ******************************************************************************************************************** 624 ********************************************************************************************************************
595 ******************************************************************************************************************** 625 ********************************************************************************************************************
@@ -733,14 +763,13 @@ int rtp_send_msg ( RTPSession* session, Tox* messenger, const uint8_t* data, uin
733/** 763/**
734 * @brief Speaks for it self. 764 * @brief Speaks for it self.
735 * 765 *
736 * @param session The control session msg belongs to. It can be NULL. 766 * @param session The control session msg belongs to. You set it as NULL when freeing recved messages.
767 * Otherwise set it to session the message was created from.
737 * @param msg The message. 768 * @param msg The message.
738 * @return void 769 * @return void
739 */ 770 */
740void rtp_free_msg ( RTPSession* session, RTPMessage* msg ) 771void rtp_free_msg ( RTPSession* session, RTPMessage* msg )
741{ 772{
742 free ( msg->data );
743
744 if ( !session ){ 773 if ( !session ){
745 free ( msg->header->csrc ); 774 free ( msg->header->csrc );
746 if ( msg->ext_header ){ 775 if ( msg->ext_header ){
@@ -793,7 +822,7 @@ RTPSession* rtp_init_session ( int payload_type,
793 return NULL; 822 return NULL;
794 } 823 }
795 824
796 RTPSession* _retu = calloc(sizeof(RTPSession), 1); 825 RTPSession* _retu = calloc(1, sizeof(RTPSession));
797 assert(_retu); 826 assert(_retu);
798 827
799 networking_registerhandler(_messenger_casted->net, payload_type, rtp_handle_packet, _retu); 828 networking_registerhandler(_messenger_casted->net, payload_type, rtp_handle_packet, _retu);
@@ -819,15 +848,15 @@ RTPSession* rtp_init_session ( int payload_type,
819 _retu->decrypt_key = decrypt_key; 848 _retu->decrypt_key = decrypt_key;
820 849
821 /* Need to allocate new memory */ 850 /* Need to allocate new memory */
822 _retu->encrypt_nonce = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); assert(_retu->encrypt_nonce); 851 _retu->encrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->encrypt_nonce);
823 _retu->decrypt_nonce = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); assert(_retu->decrypt_nonce); 852 _retu->decrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->decrypt_nonce);
824 _retu->nonce_cycle = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); assert(_retu->nonce_cycle); 853 _retu->nonce_cycle = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->nonce_cycle);
825 854
826 memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_box_NONCEBYTES); 855 memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_box_NONCEBYTES);
827 memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_box_NONCEBYTES); 856 memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_box_NONCEBYTES);
828 memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_box_NONCEBYTES); 857 memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_box_NONCEBYTES);
829 858
830 _retu->csrc = calloc(sizeof(uint32_t), 1); 859 _retu->csrc = calloc(1, sizeof (uint32_t));
831 assert(_retu->csrc); 860 assert(_retu->csrc);
832 861
833 _retu->csrc[0] = _retu->ssrc; /* Set my ssrc to the list receive */ 862 _retu->csrc[0] = _retu->ssrc; /* Set my ssrc to the list receive */
diff --git a/toxav/toxrtp.h b/toxav/toxrtp.h
index 32234ebe..9f8ae5ee 100755
--- a/toxav/toxrtp.h
+++ b/toxav/toxrtp.h
@@ -27,13 +27,14 @@
27 27
28#define RTP_VERSION 2 28#define RTP_VERSION 2
29#include <inttypes.h> 29#include <inttypes.h>
30#include <pthread.h>
30#include "../toxcore/tox.h" 31#include "../toxcore/tox.h"
31 32
32#define MAX_SEQU_NUM 65535 33#define MAX_SEQU_NUM 65535
33 34#define MAX_RTP_SIZE 1400
34 35
35/** 36/**
36 * @brief Standard rtp header. 37 * @brief Standard rtp header
37 * 38 *
38 */ 39 */
39 40
@@ -69,7 +70,7 @@ typedef struct _RTPMessage {
69 RTPHeader* header; 70 RTPHeader* header;
70 RTPExtHeader* ext_header; 71 RTPExtHeader* ext_header;
71 72
72 uint8_t* data; 73 uint8_t data[MAX_RTP_SIZE];
73 uint32_t length; 74 uint32_t length;
74 tox_IP_Port from; 75 tox_IP_Port from;
75 76