From 0fa03b924030c5791599451389ba84b81be84da8 Mon Sep 17 00:00:00 2001 From: mannol Date: Sat, 3 May 2014 01:46:03 +0200 Subject: Bunch of random changes --- toxav/Makefile.inc | 41 +- toxav/media.c | 95 ++-- toxav/media.h | 15 +- toxav/msi.c | 34 +- toxav/phone.c | 1460 ---------------------------------------------------- toxav/rtp.c | 116 ++++- toxav/rtp.h | 20 +- toxav/toxav.c | 127 ++++- toxav/toxav.h | 41 +- 9 files changed, 318 insertions(+), 1631 deletions(-) delete mode 100755 toxav/phone.c (limited to 'toxav') diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc index 0cad1840..060a760c 100644 --- a/toxav/Makefile.inc +++ b/toxav/Makefile.inc @@ -32,43 +32,4 @@ libtoxav_la_LIBADD = libtoxcore.la \ $(AV_LIBS) -endif - - - - - - -if BUILD_PHONE - - -noinst_PROGRAMS += phone - -phone_SOURCES = ../toxav/phone.c - -phone_CFLAGS = -I../toxcore \ - -I../toxav \ - $(AVFORMAT_CFLAGS) \ - $(AVCODEC_CFLAGS) \ - $(AVUTIL_CFLAGS) \ - $(AVDEVICE_CFLAGS) \ - $(SWSCALE_CFLAGS) \ - $(SDL_CFLAGS) \ - $(OPENAL_CFLAGS) - -phone_LDADD = libtoxav.la \ - libtoxcore.la \ - $(AVFORMAT_LIBS) \ - $(AVCODEC_LIBS) \ - $(AVUTIL_LIBS) \ - $(AVDEVICE_LIBS) \ - $(SWSCALE_LIBS) \ - $(SDL_LIBS) \ - $(OPENAL_LIBS) \ - $(OPUS_LIBS) \ - $(VPX_LIBS)\ - $(PTHREAD_LIBS)\ - $(NACL_LIBS) - - -endif +endif \ No newline at end of file diff --git a/toxav/media.c b/toxav/media.c index a9a4adb8..33d5d6b6 100644 --- a/toxav/media.c +++ b/toxav/media.c @@ -26,6 +26,8 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#include "../toxcore/logger.h" + #include #include #include @@ -34,17 +36,6 @@ #include "rtp.h" #include "media.h" -struct jitter_buffer { - RTPMessage **queue; - uint16_t capacity; - uint16_t size; - uint16_t front; - uint16_t rear; - uint8_t queue_ready; - uint16_t current_id; - uint32_t current_ts; - uint8_t id_set; -}; int empty_queue(struct jitter_buffer *q) { @@ -79,14 +70,7 @@ struct jitter_buffer *create_queue(int capacity) return q; } -/* returns 1 if 'a' has a higher sequence number than 'b' */ -uint8_t sequence_number_older(uint16_t sn_a, uint16_t sn_b, uint32_t ts_a, uint32_t ts_b) -{ - /* TODO: There is already this kind of function in toxrtp.c. - * Maybe merge? - */ - return (sn_a > sn_b || ts_a > ts_b); -} +#define sequnum_older(sn_a, sn_b, ts_a, ts_b) (sn_a > sn_b || ts_a > ts_b) /* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */ RTPMessage *dequeue(struct jitter_buffer *q, int *success) @@ -112,14 +96,13 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success) q->current_id = next_id; q->current_ts = next_ts; } else { - if (sequence_number_older(next_id, q->current_id, next_ts, q->current_ts)) { - /*printf("nextid: %d current: %d\n", next_id, q->current_id);*/ + if (sequnum_older(next_id, q->current_id, next_ts, q->current_ts)) { + LOGGER_DEBUG("nextid: %d current: %d\n", next_id, q->current_id); q->current_id = (q->current_id + 1) % MAX_SEQU_NUM; *success = 2; /* tell the decoder the packet is lost */ return NULL; } else { - /* packet too old */ - /*printf("packet too old\n");*/ + LOGGER_DEBUG("Packet too old"); *success = 0; return NULL; } @@ -139,12 +122,11 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success) } -int queue(struct jitter_buffer *q, RTPMessage *pk) +void queue(struct jitter_buffer* q, RTPMessage* pk) { if (q->size == q->capacity) { /* Full, empty queue */ + LOGGER_DEBUG("Queue full, emptying..."); empty_queue(q); - /*rtp_free_msg(NULL, pk);*/ - return 0; } if (q->size > 8) @@ -169,13 +151,13 @@ int queue(struct jitter_buffer *q, RTPMessage *pk) if (b < 0) b += q->capacity; - if (sequence_number_older(q->queue[b]->header->sequnum, q->queue[a]->header->sequnum, - q->queue[b]->header->timestamp, q->queue[a]->header->timestamp)) { + if (sequnum_older(q->queue[b]->header->sequnum, q->queue[a]->header->sequnum, + q->queue[b]->header->timestamp, q->queue[a]->header->timestamp)) { RTPMessage *temp; temp = q->queue[a]; q->queue[a] = q->queue[b]; q->queue[b] = temp; - /*printf("had to swap\n");*/ + LOGGER_DEBUG("Had to swap"); } else { break; } @@ -185,19 +167,14 @@ int queue(struct jitter_buffer *q, RTPMessage *pk) if (a < 0) a += q->capacity; } - - if (pk) - return 1; - - return 0; } int init_video_decoder(CodecState *cs) { - if (vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, - VPX_DECODER_ABI_VERSION) != VPX_CODEC_OK) { - /*fprintf(stderr, "Init video_decoder failed!\n");*/ + int rc = vpx_codec_dec_init_ver(&cs->v_decoder, VIDEO_CODEC_DECODER_INTERFACE, NULL, 0, VPX_DECODER_ABI_VERSION); + if ( rc != VPX_CODEC_OK) { + LOGGER_ERROR("Init video_decoder failed: %s", vpx_codec_err_to_string(rc)); return -1; } @@ -210,7 +187,7 @@ int init_audio_decoder(CodecState *cs, uint32_t audio_channels) cs->audio_decoder = opus_decoder_create(cs->audio_sample_rate, audio_channels, &rc ); if ( rc != OPUS_OK ) { - /*fprintf(stderr, "Error while starting audio decoder!\n");*/ + LOGGER_ERROR("Error while starting audio decoder: %s", opus_strerror(rc)); return -1; } @@ -221,10 +198,10 @@ int init_audio_decoder(CodecState *cs, uint32_t audio_channels) int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t video_bitrate) { vpx_codec_enc_cfg_t cfg; - int res = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); + int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0); - if (res) { - /*fprintf(stderr, "Failed to get config: %s\n", vpx_codec_err_to_string(res));*/ + if (rc) { + LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc)); return -1; } @@ -232,9 +209,10 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t cfg.g_w = width; cfg.g_h = height; - if (vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, - VPX_ENCODER_ABI_VERSION) != VPX_CODEC_OK) { - /*fprintf(stderr, "Failed to initialize encoder\n");*/ + rc = vpx_codec_enc_init_ver(&cs->v_encoder, VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0, VPX_ENCODER_ABI_VERSION); + + if ( rc != VPX_CODEC_OK) { + LOGGER_ERROR("Failed to initialize encoder: %s", vpx_codec_err_to_string(rc)); return -1; } @@ -243,13 +221,30 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t int init_audio_encoder(CodecState *cs, uint32_t audio_channels) { - int err = OPUS_OK; - cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &err); - err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate)); - err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); + int rc = OPUS_OK; + cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, audio_channels, OPUS_APPLICATION_AUDIO, &rc); + + if ( rc != OPUS_OK ) { + LOGGER_ERROR("Error while starting audio encoder: %s", opus_strerror(rc)); + return -1; + } + + rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate)); + + if ( rc != OPUS_OK ) { + LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc)); + return -1; + } + + rc = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10)); + + if ( rc != OPUS_OK ) { + LOGGER_ERROR("Error while setting encoder ctl: %s", opus_strerror(rc)); + return -1; + } - return err == OPUS_OK ? 0 : -1; + return 0; } @@ -293,7 +288,7 @@ void codec_terminate_session ( CodecState *cs ) /* TODO: Terminate video - * Do what??? + * Do what? */ if ( cs->capabilities & v_decoding ) vpx_codec_destroy(&cs->v_decoder); diff --git a/toxav/media.h b/toxav/media.h index f5c5fbe4..68694664 100644 --- a/toxav/media.h +++ b/toxav/media.h @@ -68,9 +68,22 @@ typedef struct _CodecState { } CodecState; + +struct jitter_buffer { + RTPMessage **queue; + uint16_t capacity; + uint16_t size; + uint16_t front; + uint16_t rear; + uint8_t queue_ready; + uint16_t current_id; + uint32_t current_ts; + uint8_t id_set; +}; + struct jitter_buffer *create_queue(int capacity); -int queue(struct jitter_buffer *q, RTPMessage *pk); +void queue(struct jitter_buffer *q, RTPMessage *pk); RTPMessage *dequeue(struct jitter_buffer *q, int *success); diff --git a/toxav/msi.c b/toxav/msi.c index ae6fcf84..8d4e6964 100755 --- a/toxav/msi.c +++ b/toxav/msi.c @@ -932,6 +932,7 @@ MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) if ( _call_idx == session->max_calls ) { LOGGER_WARNING("Reached maximum amount of calls!"); + return NULL; } @@ -1017,7 +1018,7 @@ int terminate_call ( MSISession *session, MSICall *call ) /********** Request handlers **********/ int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg ) { - LOGGER_DEBUG("Handling 'invite' on call: %s", call? (char*)call->id : "making new"); + LOGGER_DEBUG("Session: %p Handling 'invite' on call: %s", session, call? (char*)call->id : "making new"); if ( call ) { if ( call->peers[0] == msg->friend_id ) { @@ -1071,7 +1072,7 @@ int handle_recv_invite ( MSISession *session, MSICall* call, MSIMessage *msg ) } int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg ) { - LOGGER_DEBUG("Handling 'start' on call: %s", call->id ); + LOGGER_DEBUG("Session: %p Handling 'start' on call: %s", session, call->id ); if ( has_call_error ( session, call, msg ) == 0 ) return -1; @@ -1095,7 +1096,7 @@ int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg ) } int handle_recv_reject ( MSISession *session, MSICall* call, MSIMessage *msg ) { - LOGGER_DEBUG("Handling 'reject' on call: %s", call->id ); + LOGGER_DEBUG("Session: %p Handling 'reject' on call: %s", session, call->id); if ( has_call_error ( session, call, msg ) == 0 ) return 0; @@ -1118,7 +1119,7 @@ int handle_recv_reject ( MSISession *session, MSICall* call, MSIMessage *msg ) } int handle_recv_cancel ( MSISession *session, MSICall* call, MSIMessage *msg ) { - LOGGER_DEBUG("Handling 'cancel' on call: %s", call->id ); + LOGGER_DEBUG("Session: %p Handling 'cancel' on call: %s", session, call->id ); if ( has_call_error ( session, call, msg ) == 0 ) return 0; @@ -1137,7 +1138,7 @@ int handle_recv_cancel ( MSISession *session, MSICall* call, MSIMessage *msg ) } int handle_recv_end ( MSISession *session, MSICall* call, MSIMessage *msg ) { - LOGGER_DEBUG("Handling 'end' on call: %s", call->id ); + LOGGER_DEBUG("Session: %p Handling 'end' on call: %s", session, call->id ); if ( has_call_error ( session, call, msg ) == 0 ) return 0; @@ -1156,7 +1157,7 @@ int handle_recv_end ( MSISession *session, MSICall* call, MSIMessage *msg ) /********** Response handlers **********/ int handle_recv_ringing ( MSISession *session, MSICall* call, MSIMessage *msg ) { - LOGGER_DEBUG("Handling 'ringing' on call: %s", call->id ); + LOGGER_DEBUG("Session: %p Handling 'ringing' on call: %s", session, call->id ); if ( has_call_error ( session, call, msg ) == 0 ) return 0; @@ -1169,7 +1170,7 @@ int handle_recv_ringing ( MSISession *session, MSICall* call, MSIMessage *msg ) } int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg ) { - LOGGER_DEBUG("Handling 'starting' on call: %s", call->id ); + LOGGER_DEBUG("Session: %p Handling 'starting' on call: %s", session, call->id ); if ( has_call_error ( session, call, msg ) == 0 ) return 0; @@ -1210,7 +1211,7 @@ int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg ) } int handle_recv_ending ( MSISession *session, MSICall* call, MSIMessage *msg ) { - LOGGER_DEBUG("Handling 'ending' on call: %s", call->id ); + LOGGER_DEBUG("Session: %p Handling 'ending' on call: %s", session, call->id ); if ( has_call_error ( session, call, msg ) == 0 ) return 0; @@ -1232,7 +1233,7 @@ int handle_recv_error ( MSISession *session, MSICall* call, MSIMessage *msg ) return -1; } - LOGGER_DEBUG("Handling 'error' on call: %s", call->id ); + LOGGER_DEBUG("Session: %p Handling 'error' on call: %s", session, call->id ); /* Handle error accordingly */ if ( msg->reason.header_value ) { @@ -1490,7 +1491,8 @@ int msi_terminate_session ( MSISession *session ) } m_callback_msi_packet((struct Messenger *) session->messenger_handle, NULL, NULL); - + + LOGGER_DEBUG("Terminated session: %p", session); free ( session ); return _status; } @@ -1507,7 +1509,7 @@ int msi_terminate_session ( MSISession *session ) */ int msi_invite ( MSISession* session, uint32_t* call_index, MSICallType call_type, uint32_t rngsec, uint32_t friend_id ) { - LOGGER_DEBUG("Inviting friend: %u", friend_id); + LOGGER_DEBUG("Session: %p Inviting friend: %u", session, friend_id); MSIMessage *_msg_invite = msi_new_message ( TYPE_REQUEST, stringify_request ( invite ) ); @@ -1553,7 +1555,7 @@ int msi_invite ( MSISession* session, uint32_t* call_index, MSICallType call_typ */ int msi_hangup ( MSISession* session, uint32_t call_index ) { - LOGGER_DEBUG("Hanging up call: %u", call_index); + LOGGER_DEBUG("Session: %p Hanging up call: %u", session, call_index); if ( call_index >= session->max_calls || !session->calls[call_index] ) { LOGGER_ERROR("Invalid call index!"); @@ -1592,7 +1594,7 @@ int msi_hangup ( MSISession* session, uint32_t call_index ) */ int msi_answer ( MSISession* session, uint32_t call_index, MSICallType call_type ) { - LOGGER_DEBUG("Answering call: %u", call_index); + LOGGER_DEBUG("Session: %p Answering call: %u", session, call_index); if ( call_index >= session->max_calls || !session->calls[call_index] ){ LOGGER_ERROR("Invalid call index!"); @@ -1641,7 +1643,7 @@ int msi_answer ( MSISession* session, uint32_t call_index, MSICallType call_type */ int msi_cancel ( MSISession *session, uint32_t call_index, uint32_t peer, const char *reason ) { - LOGGER_DEBUG("Canceling call: %u; reason:", call_index, reason? reason : "Unknown"); + LOGGER_DEBUG("Session: %p Canceling call: %u; reason:", session, call_index, reason? reason : "Unknown"); if ( call_index >= session->max_calls || !session->calls[call_index] ){ LOGGER_ERROR("Invalid call index!"); @@ -1670,7 +1672,7 @@ int msi_cancel ( MSISession *session, uint32_t call_index, uint32_t peer, const */ int msi_reject ( MSISession *session, uint32_t call_index, const uint8_t *reason ) { - LOGGER_DEBUG("Rejecting call: %u; reason:", call_index, reason? (char*)reason : "Unknown"); + LOGGER_DEBUG("Session: %p Rejecting call: %u; reason:", session, call_index, reason? (char*)reason : "Unknown"); if ( call_index >= session->max_calls || !session->calls[call_index] ){ LOGGER_ERROR("Invalid call index!"); @@ -1699,7 +1701,7 @@ int msi_reject ( MSISession *session, uint32_t call_index, const uint8_t *reason */ int msi_stopcall ( MSISession *session, uint32_t call_index ) { - LOGGER_DEBUG("Stopping call index: %u", call_index); + LOGGER_DEBUG("Session: %p Stopping call index: %u", session, call_index); if ( call_index >= session->max_calls || !session->calls[call_index] ) return -1; diff --git a/toxav/phone.c b/toxav/phone.c deleted file mode 100755 index 2b33f7e9..00000000 --- a/toxav/phone.c +++ /dev/null @@ -1,1460 +0,0 @@ -/** phone.c - * - * NOTE NOTE NOTE NOTE NOTE NOTE - * - * This file is for testing/reference purposes only, hence - * it is _poorly_ designed and it does not fully reflect the - * quaility of msi nor rtp. Although toxmsi* and toxrtp* are tested - * there is always possiblity of crashes. If crash occures, - * contact me ( mannol ) on either irc channel #tox-dev @ freenode.net:6667 - * or eniz_vukovic@hotmail.com - * - * NOTE NOTE NOTE NOTE NOTE NOTE - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -#define _BSD_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include - -//#include "media.h" -#include "toxav.h" -#include "event.h" -#include "../toxcore/tox.h" - -#define AUDIO_FRAME_SIZE (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000) - -#ifdef TOX_FFMPEG -/* Video encoding/decoding */ -#include -#include -#include -#include -#include -#endif - -#include -#include -#include -#include - -/* the quit event for SDL */ -#define FF_QUIT_EVENT (SDL_USEREVENT + 2) - -#ifdef __linux__ -#define VIDEO_DRIVER "video4linux2" -#define DEFAULT_WEBCAM "/dev/video0" -#endif - -#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) -#define VIDEO_DRIVER "vfwcap" -#define DEFAULT_WEBCAM "0" -#endif - - -/* Define client version */ -#define _USERAGENT "v.0.3.0" - - -struct SDL_Surface *screen; - -typedef struct { - struct SDL_Overlay *bmp; - int width, height; -} VideoPicture; - - -typedef struct av_friend_s { - int _id; - int _active; /* 0=false; 1=true; */ -} av_friend_t; - -typedef struct av_session_s { - /* Encoding/decoding/capturing/playing */ - ToxAv *av; - - VideoPicture video_picture; - struct ALCdevice *audio_capture_device; - - /* context for converting image format to something SDL can use*/ - struct SwsContext *sws_SDL_r_ctx; - - /* context for converting webcam image format to something the video encoder can use */ - struct SwsContext *sws_ctx; - - /* Thread running control */ - int running_decaud, running_encaud, - running_decvid, running_encvid; - - pthread_mutex_t _mutex; - - Tox *_messenger; - av_friend_t *_friends; - int _friend_cout; - char _my_public_id[200]; -#ifdef TOX_FFMPEG - AVInputFormat *video_input_format; - AVFormatContext *video_format_ctx; - uint8_t video_stream; - AVCodecContext *webcam_decoder_ctx; - AVCodec *webcam_decoder; -#endif -} av_session_t; -av_session_t *_phone; - -void av_allocate_friend(av_session_t *_phone, int _id, int _active) -{ - static int _new_id = 0; - - if ( !_phone->_friends ) { - _phone->_friends = calloc(sizeof(av_friend_t), 1); - _phone->_friend_cout = 1; - } else { - _phone->_friend_cout ++; - _phone->_friends = realloc(_phone->_friends, sizeof(av_friend_t) * _phone->_friend_cout); - } - - if ( _id == -1 ) { - _phone->_friends->_id = _new_id; - _new_id ++; - } else _phone->_friends->_id = _id; - - _phone->_friends->_active = _active; -} -av_friend_t *av_get_friend(av_session_t *_phone, int _id) -{ - av_friend_t *_friends = _phone->_friends; - - if ( !_friends ) return NULL; - - int _it = 0; - - for (; _it < _phone->_friend_cout; _it ++) - if ( _friends[_it]._id == _id ) - return _friends + _it; - - return NULL; -} - - -/***************** MISC *****************/ - -void INFO (const char *_format, ...) -{ - printf("\r[!] "); - va_list _arg; - va_start (_arg, _format); - vfprintf (stdout, _format, _arg); - va_end (_arg); - printf("\n\r >> "); - fflush(stdout); -} - -unsigned char *hex_string_to_bin(char hex_string[]) -{ - size_t i, len = strlen(hex_string); - unsigned char *val = calloc(sizeof(unsigned char), len); - char *pos = hex_string; - - for (i = 0; i < len; ++i, pos += 2) - sscanf(pos, "%2hhx", &val[i]); - - return val; -} - -int getinput( char *_buff, size_t _limit, int *_len ) -{ - if ( fgets(_buff, _limit, stdin) == NULL ) - return -1; - - *_len = strlen(_buff) - 1; - - /* Get rid of newline */ - _buff[*_len] = '\0'; - - return 0; -} - -char *trim_spaces ( char *buff ) -{ - - int _i = 0, _len = strlen(buff); - - char *container = calloc(sizeof(char), _len); - int _ci = 0; - - for ( ; _i < _len; _i++ ) { - while ( _i < _len && buff[_i] == ' ' ) - _i++; - - if ( _i < _len ) { - container[_ci] = buff[_i]; - _ci ++; - } - } - - memcpy( buff, container, _ci ); - buff[_ci] = '\0'; - free(container); - return buff; -} - -#define FRADDR_TOSTR_CHUNK_LEN 8 - -static void fraddr_to_str(uint8_t *id_bin, char *id_str) -{ - uint i, delta = 0, pos_extra = 0, sum_extra = 0; - - for (i = 0; i < TOX_FRIEND_ADDRESS_SIZE; i++) { - sprintf(&id_str[2 * i + delta], "%02hhX", id_bin[i]); - - if ((i + 1) == TOX_CLIENT_ID_SIZE) - pos_extra = 2 * (i + 1) + delta; - - if (i >= TOX_CLIENT_ID_SIZE) - sum_extra |= id_bin[i]; - - if (!((i + 1) % FRADDR_TOSTR_CHUNK_LEN)) { - id_str[2 * (i + 1) + delta] = ' '; - delta++; - } - } - - id_str[2 * i + delta] = 0; - - if (!sum_extra) - id_str[pos_extra] = 0; -} - -/********************************************* - ********************************************* - ********************************************* - ********************************************* - ********************************************* - ********************************************* - ********************************************* - ********************************************* - */ - - -/* - * How av stuff _should_ look like - */ -/* -int display_received_frame(av_session_t* _phone, vpx_image_t *image) -{ - CodecState* cs = get_cs_temp(_phone->av); - AVPicture pict; - SDL_LockYUVOverlay(_phone->video_picture.bmp); - - pict.data[0] = _phone->video_picture.bmp->pixels[0]; - pict.data[1] = _phone->video_picture.bmp->pixels[2]; - pict.data[2] = _phone->video_picture.bmp->pixels[1]; - pict.linesize[0] = _phone->video_picture.bmp->pitches[0]; - pict.linesize[1] = _phone->video_picture.bmp->pitches[2]; - pict.linesize[2] = _phone->video_picture.bmp->pitches[1]; - */ -/* Convert the image into YUV format that SDL uses *//* -sws_scale(_phone->sws_SDL_r_ctx, (uint8_t const * const *)r_video_frame->data, r_video_frame->linesize, 0, - cs->video_decoder_ctx->height, pict.data, pict.linesize ); - -SDL_UnlockYUVOverlay(_phone->video_picture.bmp); -SDL_Rect rect; -rect.x = 0; -rect.y = 0; -rect.w = cs->video_decoder_ctx->width; -rect.h = cs->video_decoder_ctx->height; -SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect); -return 1; -} -*/ -#ifdef TOX_FFMPEG -void *encode_video_thread(void *arg) -{ - INFO("Started encode video thread!"); - - av_session_t *_phone = arg; - - _phone->running_encvid = 1; - //CodecState *cs = get_cs_temp(_phone->av); - AVPacket pkt1, *packet = &pkt1; - //int p = 0; - //int got_packet; - int video_frame_finished; - AVFrame *s_video_frame; - AVFrame *webcam_frame; - s_video_frame = avcodec_alloc_frame(); - webcam_frame = avcodec_alloc_frame(); - //AVPacket enc_video_packet; - - uint8_t *buffer; - int numBytes; - /* Determine required buffer size and allocate buffer */ - numBytes = avpicture_get_size(PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height); - buffer = (uint8_t *)av_calloc(numBytes * sizeof(uint8_t), 1); - avpicture_fill((AVPicture *)s_video_frame, buffer, PIX_FMT_YUV420P, _phone->webcam_decoder_ctx->width, - _phone->webcam_decoder_ctx->height); - _phone->sws_ctx = sws_getContext(_phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, - _phone->webcam_decoder_ctx->pix_fmt, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, - PIX_FMT_YUV420P, - SWS_BILINEAR, NULL, NULL, NULL); - - - vpx_image_t *image = - vpx_img_alloc(NULL, VPX_IMG_FMT_I420, _phone->webcam_decoder_ctx->width, _phone->webcam_decoder_ctx->height, 1); - - //uint32_t frame_counter = 0; - while (_phone->running_encvid) { - - if (av_read_frame(_phone->video_format_ctx, packet) < 0) { - printf("error reading frame\n"); - - if (_phone->video_format_ctx->pb->error != 0) - break; - - continue; - } - - if (packet->stream_index == _phone->video_stream) { - if (avcodec_decode_video2(_phone->webcam_decoder_ctx, webcam_frame, &video_frame_finished, packet) < 0) { - printf("couldn't decode\n"); - continue; - } - - av_free_packet(packet); - sws_scale(_phone->sws_ctx, (uint8_t const * const *)webcam_frame->data, webcam_frame->linesize, 0, - _phone->webcam_decoder_ctx->height, s_video_frame->data, s_video_frame->linesize); - /* create a new I-frame every 60 frames */ - //++p; - /* - if (p == 60) { - - s_video_frame->pict_type = AV_PICTURE_TYPE_BI ; - } else if (p == 61) { - s_video_frame->pict_type = AV_PICTURE_TYPE_I ; - p = 0; - } else { - s_video_frame->pict_type = AV_PICTURE_TYPE_P ; - }*/ - - if (video_frame_finished) { - memcpy(image->planes[VPX_PLANE_Y], s_video_frame->data[0], - s_video_frame->linesize[0] * _phone->webcam_decoder_ctx->height); - memcpy(image->planes[VPX_PLANE_U], s_video_frame->data[1], - s_video_frame->linesize[1] * _phone->webcam_decoder_ctx->height / 2); - memcpy(image->planes[VPX_PLANE_V], s_video_frame->data[2], - s_video_frame->linesize[2] * _phone->webcam_decoder_ctx->height / 2); - toxav_send_video (_phone->av, image); - //if (avcodec_encode_video2(cs->video_encoder_ctx, &enc_video_packet, s_video_frame, &got_packet) < 0) { - /*if (vpx_codec_encode(&cs->v_encoder, image, frame_counter, 1, 0, 0) != VPX_CODEC_OK) { - printf("could not encode video frame\n"); - continue; - } - ++frame_counter; - - vpx_codec_iter_t iter = NULL; - vpx_codec_cx_pkt_t *pkt; - while( (pkt = vpx_codec_get_cx_data(&cs->v_encoder, &iter)) ) { - if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) - toxav_send_rtp_payload(_phone->av, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz); - }*/ - //if (!got_packet) { - // continue; - //} - - //if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n"); - - //toxav_send_rtp_payload(_phone->av, TypeVideo, enc_video_packet.data, enc_video_packet.size); - - //av_free_packet(&enc_video_packet); - } - } else { - av_free_packet(packet); - } - } - - vpx_img_free(image); - - /* clean up codecs */ - //pthread_mutex_lock(&cs->ctrl_mutex); - av_free(buffer); - av_free(webcam_frame); - av_free(s_video_frame); - sws_freeContext(_phone->sws_ctx); - //avcodec_close(webcam_decoder_ctx); - //avcodec_close(cs->video_encoder_ctx); - //pthread_mutex_unlock(&cs->ctrl_mutex); - - _phone->running_encvid = -1; - - pthread_exit ( NULL ); -} -#endif - -void *encode_audio_thread(void *arg) -{ - INFO("Started encode audio thread!"); - av_session_t *_phone = arg; - _phone->running_encaud = 1; - - int ret = 0; - int16_t frame[4096]; - int frame_size = AUDIO_FRAME_SIZE; - ALint sample = 0; - alcCaptureStart((ALCdevice *)_phone->audio_capture_device); - while (_phone->running_encaud) { - - alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample); - - if (sample >= frame_size) { - alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size); - - ret = toxav_send_audio(_phone->av, frame, frame_size); - - if (ret < 0) printf("Could not encode or send audio packet\n"); - - } else { - usleep(1000); - } - } - - /* clean up codecs * - pthread_mutex_lock(&cs->ctrl_mutex);* / - alcCaptureStop((ALCdevice*)_phone->audio_capture_device); - alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device); - / *pthread_mutex_unlock(&cs->ctrl_mutex);*/ - _phone->running_encaud = -1; - pthread_exit ( NULL ); -} - -void convert_to_rgb(vpx_image_t *img, unsigned char *out) -{ - const int w = img->d_w; - const int w2 = w / 2; - const int pstride = w * 3; - const int h = img->d_h; - const int h2 = h / 2; - - const int strideY = img->stride[0]; - const int strideU = img->stride[1]; - const int strideV = img->stride[2]; - int posy, posx; - - for (posy = 0; posy < h2; posy++) { - unsigned char *dst = out + pstride * (posy * 2); - unsigned char *dst2 = out + pstride * (posy * 2 + 1); - const unsigned char *srcY = img->planes[0] + strideY * posy * 2; - const unsigned char *srcY2 = img->planes[0] + strideY * (posy * 2 + 1); - const unsigned char *srcU = img->planes[1] + strideU * posy; - const unsigned char *srcV = img->planes[2] + strideV * posy; - - for (posx = 0; posx < w2; posx++) { - unsigned char Y, U, V; - short R, G, B; - short iR, iG, iB; - - U = *(srcU++); - V = *(srcV++); - iR = (351 * (V - 128)) / 256; - iG = - (179 * (V - 128)) / 256 - (86 * (U - 128)) / 256; - iB = (444 * (U - 128)) / 256; - - Y = *(srcY++); - R = Y + iR ; - G = Y + iG ; - B = Y + iB ; - R = (R < 0 ? 0 : (R > 255 ? 255 : R)); - G = (G < 0 ? 0 : (G > 255 ? 255 : G)); - B = (B < 0 ? 0 : (B > 255 ? 255 : B)); - *(dst++) = R; - *(dst++) = G; - *(dst++) = B; - - Y = *(srcY2++); - R = Y + iR ; - G = Y + iG ; - B = Y + iB ; - R = (R < 0 ? 0 : (R > 255 ? 255 : R)); - G = (G < 0 ? 0 : (G > 255 ? 255 : G)); - B = (B < 0 ? 0 : (B > 255 ? 255 : B)); - *(dst2++) = R; - *(dst2++) = G; - *(dst2++) = B; - - Y = *(srcY++) ; - R = Y + iR ; - G = Y + iG ; - B = Y + iB ; - R = (R < 0 ? 0 : (R > 255 ? 255 : R)); - G = (G < 0 ? 0 : (G > 255 ? 255 : G)); - B = (B < 0 ? 0 : (B > 255 ? 255 : B)); - *(dst++) = R; - *(dst++) = G; - *(dst++) = B; - - Y = *(srcY2++); - R = Y + iR ; - G = Y + iG ; - B = Y + iB ; - R = (R < 0 ? 0 : (R > 255 ? 255 : R)); - G = (G < 0 ? 0 : (G > 255 ? 255 : G)); - B = (B < 0 ? 0 : (B > 255 ? 255 : B)); - *(dst2++) = R; - *(dst2++) = G; - *(dst2++) = B; - } - } -} - -#define mask32(BYTE) (*(uint32_t *)(uint8_t [4]){ [BYTE] = 0xff }) - -void *decode_video_thread(void *arg) -{ - INFO("Started decode video thread!"); - av_session_t *_phone = arg; - _phone->running_decvid = 1; - - //CodecState *cs = get_cs_temp(_phone->av); - //cs->video_stream = 0; - - //int recved_size; - //uint8_t dest[RTP_PAYLOAD_SIZE]; - - //int dec_frame_finished; - //AVFrame *r_video_frame; - //r_video_frame = avcodec_alloc_frame(); - //AVPacket dec_video_packet; - //av_new_packet (&dec_video_packet, 65536); - int width = 0; - int height = 0; - - while (_phone->running_decvid) { - //recved_size = toxav_recv_rtp_payload(_phone->av, TypeVideo, dest); - //if (recved_size) { - vpx_image_t *image = NULL; - - if (toxav_recv_video(_phone->av, &image) == 0 && image) { - //memcpy(dec_video_packet.data, dest, recved_size); - //dec_video_packet.size = recved_size; - - //avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet); - - //if (dec_frame_finished) { - - /* Check if size has changed */ - if (image->d_w != width || image->d_h != height) { - - width = image->d_w; - height = image->d_h; - - printf("w: %d h: %d \n", width, height); - - screen = SDL_SetVideoMode(width, height, 0, 0); - - //if (_phone->video_picture.bmp) - // SDL_FreeYUVOverlay(_phone->video_picture.bmp); - - //_phone->video_picture.bmp = SDL_CreateYUVOverlay(width, height, SDL_YV12_OVERLAY, screen); - // _phone->sws_SDL_r_ctx = sws_getContext(width, height, cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P, - // SWS_BILINEAR, NULL, NULL, NULL); - } - - uint8_t *rgb_image = malloc(width * height * 3); - convert_to_rgb(image, rgb_image); - SDL_Surface *img_surface = SDL_CreateRGBSurfaceFrom(rgb_image, width, height, 24, width * 3, mask32(0), mask32(1), - mask32(2), 0); - - if (SDL_BlitSurface(img_surface, NULL, screen, NULL) == 0) - SDL_UpdateRect(screen, 0, 0, 0, 0); - - /* - SDL_LockYUVOverlay(_phone->video_picture.bmp); - memcpy(_phone->video_picture.bmp->pixels[0], image->planes[VPX_PLANE_Y], _phone->video_picture.bmp->pitches[0] * height); - memcpy(_phone->video_picture.bmp->pixels[1], image->planes[VPX_PLANE_V], _phone->video_picture.bmp->pitches[1] * height / 2); - memcpy(_phone->video_picture.bmp->pixels[2], image->planes[VPX_PLANE_U], _phone->video_picture.bmp->pitches[2] * height / 2); - - SDL_Rect rect; - rect.x = 0; - rect.y = 0; - rect.w = width; - rect.h = height; - SDL_DisplayYUVOverlay(_phone->video_picture.bmp, &rect);*/ - free(rgb_image); - //display_received_frame(_phone, image); - - } //else { - - /* TODO: request the sender to create a new i-frame immediatly */ - //printf("Bad video packet\n"); - //} - //} - - usleep(1000); - } - - /* clean up codecs */ - //av_free(r_video_frame); - - //pthread_mutex_lock(&cs->ctrl_mutex); - //avcodec_close(cs->video_decoder_ctx); - //pthread_mutex_unlock(&cs->ctrl_mutex); - - _phone->running_decvid = -1; - - pthread_exit ( NULL ); -} - -void *decode_audio_thread(void *arg) -{ - INFO("Started decode audio thread!"); - av_session_t *_phone = arg; - _phone->running_decaud = 1; - - //int recved_size; - //uint8_t dest [RTP_PAYLOAD_SIZE]; - - int frame_size = AUDIO_FRAME_SIZE; - //int data_size; - - ALCdevice *dev; - ALCcontext *ctx; - ALuint source, *buffers; - dev = alcOpenDevice(NULL); - ctx = alcCreateContext(dev, NULL); - alcMakeContextCurrent(ctx); - int openal_buffers = 5; - - buffers = calloc(sizeof(ALuint) * openal_buffers, 1); - alGenBuffers(openal_buffers, buffers); - alGenSources((ALuint)1, &source); - alSourcei(source, AL_LOOPING, AL_FALSE); - - ALuint buffer; - ALint ready; - - uint16_t zeros[frame_size]; - memset(zeros, 0, frame_size); - int16_t PCM[frame_size]; - - int i; - - for (i = 0; i < openal_buffers; ++i) { - alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); - } - - alSourceQueueBuffers(source, openal_buffers, buffers); - alSourcePlay(source); - - if (alGetError() != AL_NO_ERROR) { - fprintf(stderr, "Error starting audio\n"); - goto ending; - } - - int dec_frame_len = 0; - - while (_phone->running_decaud) { - - alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready); - - if (ready <= 0) - continue; - - dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM); - - /* Play the packet */ - if (dec_frame_len > 0) { - alSourceUnqueueBuffers(source, 1, &buffer); - alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000); - int error = alGetError(); - - if (error != AL_NO_ERROR) { - fprintf(stderr, "Error setting buffer %d\n", error); - break; - } - - alSourceQueueBuffers(source, 1, &buffer); - - if (alGetError() != AL_NO_ERROR) { - fprintf(stderr, "Error: could not buffer audio\n"); - break; - } - - alGetSourcei(source, AL_SOURCE_STATE, &ready); - - if (ready != AL_PLAYING) alSourcePlay(source); - } - - usleep(1000); - } - - -ending: - /* clean up codecs */ - //pthread_mutex_lock(&cs->ctrl_mutex); - /* - alDeleteSources(1, &source); - alDeleteBuffers(openal_buffers, buffers); - alcMakeContextCurrent(NULL); - alcDestroyContext(ctx); - alcCloseDevice(dev); - */ - //pthread_mutex_unlock(&cs->ctrl_mutex); - - _phone->running_decaud = -1; - - pthread_exit ( NULL ); -} - - - -void *one_threaded_audio(void *arg) -{ - INFO("Started audio thread!"); - av_session_t *_phone = arg; - _phone->running_decaud = 1; - - //int recved_size; - //uint8_t dest [RTP_PAYLOAD_SIZE]; - - int frame_size = AUDIO_FRAME_SIZE; - - int16_t frame[4096]; - ALint sample = 0; - alcCaptureStart((ALCdevice *)_phone->audio_capture_device); - - ALCdevice *dev; - ALCcontext *ctx; - ALuint source, *buffers; - dev = alcOpenDevice(NULL); - ctx = alcCreateContext(dev, NULL); - alcMakeContextCurrent(ctx); - int openal_buffers = 5; - - buffers = calloc(sizeof(ALuint) * openal_buffers, 1); - alGenBuffers(openal_buffers, buffers); - alGenSources((ALuint)1, &source); - alSourcei(source, AL_LOOPING, AL_FALSE); - - ALuint buffer; - ALint ready; - - uint16_t zeros[frame_size]; - memset(zeros, 0, frame_size); - int16_t PCM[frame_size]; - - int i; - - for (i = 0; i < openal_buffers; ++i) { - alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000); - } - - alSourceQueueBuffers(source, openal_buffers, buffers); - alSourcePlay(source); - - if (alGetError() != AL_NO_ERROR) { - fprintf(stderr, "Error starting audio\n"); - goto ending; - } - - int dec_frame_len; - - while (_phone->running_decaud) { - - // combo - alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample); - - // record and send - if (sample >= frame_size) { - alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size); - - if (toxav_send_audio(_phone->av, frame, frame_size) < 0) - printf("Could not encode or send audio packet\n"); - - } else { - usleep(5000); - } - - // play received - - alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready); - - if (ready <= 0) - continue; - - dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM); - - /* Play the packet */ - if (dec_frame_len > 0) { - alSourceUnqueueBuffers(source, 1, &buffer); - alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000); - int error = alGetError(); - - if (error != AL_NO_ERROR) { - fprintf(stderr, "Error setting buffer %d\n", error); - break; - } - - alSourceQueueBuffers(source, 1, &buffer); - - if (alGetError() != AL_NO_ERROR) { - fprintf(stderr, "Error: could not buffer audio\n"); - break; - } - - alGetSourcei(source, AL_SOURCE_STATE, &ready); - - if (ready != AL_PLAYING) alSourcePlay(source); - } - - usleep(1000); - } - - - ending: - _phone->running_decaud = -1; - - pthread_exit ( NULL ); -} - - -int phone_startmedia_loop ( ToxAv *arg ) -{ - if ( !arg ) { - return -1; - } - - toxav_prepare_transmission(arg, 1); - - /* - * Rise all threads - */ -#ifdef TOX_FFMPEG - - /* Only checks for last peer */ - if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo && - 0 > event.rise(encode_video_thread, _phone) ) { - INFO("Error while starting encode_video_thread()"); - return -1; - } - -#endif - - /* Always send audio */ - /*if ( 0 > event.rise(encode_audio_thread, toxav_get_agent_handler(arg)) ) { - INFO("Error while starting encode_audio_thread()"); - return -1; - } */ - - /* Only checks for last peer */ - if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo && - 0 > event.rise(decode_video_thread, _phone) ) { - INFO("Error while starting decode_video_thread()"); - return -1; - } - - /*if ( 0 > event.rise(decode_audio_thread, toxav_get_agent_handler(arg)) ) { - INFO("Error while starting decode_audio_thread()"); - return -1; - } */ - - - /* One threaded audio */ - - if ( 0 > event.rise(one_threaded_audio, _phone) ) { - INFO ("Shit-head"); - return -1; - } - - return 0; -} - - - - - - -/********************************************* - ********************************************* - ********************************************* - ********************************************* - ********************************************* - ********************************************* - ********************************************* - ********************************************* - */ - - -/* Some example callbacks */ - -void callback_recv_invite ( void *_arg ) -{ - assert(_arg); - - switch ( toxav_get_peer_transmission_type(_arg, 0) ) { - case TypeAudio: - INFO( "Incoming audio call!"); - break; - - case TypeVideo: - INFO( "Incoming video call!"); - break; - } - -} -void callback_recv_ringing ( void *_arg ) -{ - INFO ( "Ringing!" ); -} -void callback_recv_starting ( void *_arg ) -{ - if ( 0 != phone_startmedia_loop(_arg) ) { - INFO("Starting call failed!"); - } else { - INFO ("Call started! ( press h to hangup )"); - } - -} -void callback_recv_ending ( void *_arg ) -{ - INFO ( "Call ended!" ); - _phone->running_encaud = 0; - _phone->running_decaud = 0; - _phone->running_encvid = 0; - _phone->running_decvid = 0; - - /* Wait until all threads are done */ - usleep(100000); - - INFO ( "Call ended!" ); -} - -void callback_recv_error ( void *_arg ) -{ - /*MSISession* _session = _arg; - - INFO( "Error: %s", _session->last_error_str ); */ -} - -void callback_call_started ( void *_arg ) -{ - if ( 0 != phone_startmedia_loop(_arg) ) { - INFO("Starting call failed!"); - } else { - INFO ("Call started! ( press h to hangup )"); - } - -} -void callback_call_canceled ( void *_arg ) -{ - INFO ( "Call canceled!" ); -} -void callback_call_rejected ( void *_arg ) -{ - INFO ( "Call rejected!" ); -} -void callback_call_ended ( void *_arg ) -{ - _phone->running_encaud = 0; - _phone->running_decaud = 0; - _phone->running_encvid = 0; - _phone->running_decvid = 0; - - /* Wait until all threads are done - - while ( _phone->running_encaud != -1 || - _phone->running_decaud != -1 || - _phone->running_encvid != -1 || - _phone->running_decvid != -1 ) - - usleep(1000000);*/ - - while (_phone->running_decaud != -1) usleep(1000000); - - toxav_kill_transmission(_phone->av); - INFO ( "Call ended!" ); -} - -void callback_requ_timeout ( void *_arg ) -{ - INFO( "No answer! " ); -} - -av_session_t *av_init_session() -{ - av_session_t *_retu = malloc(sizeof(av_session_t)); - - /* Initialize our mutex */ - pthread_mutex_init ( &_retu->_mutex, NULL ); - - _retu->_messenger = tox_new(1); - - if ( !_retu->_messenger ) { - fprintf ( stderr, "tox_new() failed!\n" ); - return NULL; - } - - _retu->_friends = NULL; - - - const ALchar *_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); - int i = 0; - const ALchar *device_names[20]; - - if ( _device_list ) { - INFO("\nAvailable Capture Devices are:"); - - while (*_device_list ) { - device_names[i] = _device_list; - INFO("%d) %s", i, device_names[i]); - _device_list += strlen( _device_list ) + 1; - ++i; - } - } - - INFO("Enter capture device number"); - - char dev[2]; - char *left; - char *warned_ = fgets(dev, 2, stdin); - (void)warned_; - long selection = strtol(dev, &left, 10); - - if ( *left ) { - printf("'%s' is not a number!", dev); - fflush(stdout); - exit(EXIT_FAILURE); - } else { - INFO("Selected: %d ( %s )", selection, device_names[selection]); - } - - _retu->audio_capture_device = - (struct ALCdevice *)alcCaptureOpenDevice( - device_names[selection], av_DefaultSettings.audio_sample_rate, AL_FORMAT_MONO16, AUDIO_FRAME_SIZE * 4); - - - if (alcGetError((ALCdevice *)_retu->audio_capture_device) != AL_NO_ERROR) { - printf("Could not start capture device! %d\n", alcGetError((ALCdevice *)_retu->audio_capture_device)); - return 0; - } - - uint16_t height = 0, width = 0; -#ifdef TOX_FFMPEG - avdevice_register_all(); - avcodec_register_all(); - av_register_all(); - - _retu->video_input_format = av_find_input_format(VIDEO_DRIVER); - - if (avformat_open_input(&_retu->video_format_ctx, DEFAULT_WEBCAM, _retu->video_input_format, NULL) != 0) { - fprintf(stderr, "Opening video_input_format failed!\n"); - //return -1; - goto failed_init_ffmpeg; - } - - avformat_find_stream_info(_retu->video_format_ctx, NULL); - av_dump_format(_retu->video_format_ctx, 0, DEFAULT_WEBCAM, 0); - - for (i = 0; i < _retu->video_format_ctx->nb_streams; ++i) { - if (_retu->video_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - _retu->video_stream = i; - break; - } - } - - _retu->webcam_decoder_ctx = _retu->video_format_ctx->streams[_retu->video_stream]->codec; - _retu->webcam_decoder = avcodec_find_decoder(_retu->webcam_decoder_ctx->codec_id); - - if (_retu->webcam_decoder == NULL) { - fprintf(stderr, "Unsupported codec!\n"); - //return -1; - goto failed_init_ffmpeg; - } - - if (_retu->webcam_decoder_ctx == NULL) { - fprintf(stderr, "Init webcam_decoder_ctx failed!\n"); - //return -1; - goto failed_init_ffmpeg; - } - - if (avcodec_open2(_retu->webcam_decoder_ctx, _retu->webcam_decoder, NULL) < 0) { - fprintf(stderr, "Opening webcam decoder failed!\n"); - //return -1; - goto failed_init_ffmpeg; - } - - width = _retu->webcam_decoder_ctx->width; - height = _retu->webcam_decoder_ctx->height; - -failed_init_ffmpeg: ; -#endif - uint8_t _byte_address[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(_retu->_messenger, _byte_address ); - fraddr_to_str( _byte_address, _retu->_my_public_id ); - - ToxAvCodecSettings cs = av_DefaultSettings; - cs.video_height = height; - cs.video_width = width; - _retu->av = toxav_new(_retu->_messenger, &cs); - - /* ------------------ */ - - toxav_register_callstate_callback(callback_call_started, av_OnStart, _retu->av); - toxav_register_callstate_callback(callback_call_canceled, av_OnCancel, _retu->av); - toxav_register_callstate_callback(callback_call_rejected, av_OnReject, _retu->av); - toxav_register_callstate_callback(callback_call_ended, av_OnEnd, _retu->av); - toxav_register_callstate_callback(callback_recv_invite, av_OnInvite, _retu->av); - - toxav_register_callstate_callback(callback_recv_ringing, av_OnRinging, _retu->av); - toxav_register_callstate_callback(callback_recv_starting, av_OnStarting, _retu->av); - toxav_register_callstate_callback(callback_recv_ending, av_OnEnding, _retu->av); - - toxav_register_callstate_callback(callback_recv_error, av_OnError, _retu->av); - toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, _retu->av); - - /* ------------------ */ - - return _retu; -} - -int av_terminate_session(av_session_t *_phone) -{ - _phone->running_decaud = 0; - usleep(100000); /* Wait for tox_poll to end */ - - toxav_kill(_phone->av); - printf("\r[i] KILLED AV ARGH!\n"); - - usleep(1000000); /* Wait for cancel request to be sent */ - Tox *_p = _phone->_messenger; - _phone->_messenger = NULL; - tox_kill(_p); - - - free(_phone->_friends); - pthread_mutex_destroy ( &_phone->_mutex ); - - free(_phone); - - printf("\r[i] Quit!\n"); - return 0; -} - -/****** AV HELPER FUNCTIONS ******/ - -/* Auto accept friend request */ -void av_friend_requ(Tox *_messenger, uint8_t *_public_key, uint8_t *_data, uint16_t _length, void *_userdata) -{ - av_session_t *_phone = _userdata; - av_allocate_friend (_phone, -1, 0); - - INFO("Got friend request with message: %s", _data); - - tox_add_friend_norequest(_phone->_messenger, _public_key); - - INFO("Auto-accepted! Friend id: %d", _phone->_friends->_id ); -} - -void av_friend_active(Tox *_messenger, int _friendnumber, uint8_t *_string, uint16_t _length, void *_userdata) -{ - av_session_t *_phone = _userdata; - INFO("Friend no. %d is online", _friendnumber); - - av_friend_t *_this_friend = av_get_friend(_phone, _friendnumber); - - if ( !_this_friend ) { - INFO("But it's not registered!"); - return; - } - - (*_this_friend)._active = 1; -} - -int av_add_friend(av_session_t *_phone, char *_friend_hash) -{ - trim_spaces(_friend_hash); - - unsigned char *_bin_string = hex_string_to_bin(_friend_hash); - int _number = tox_add_friend(_phone->_messenger, _bin_string, (uint8_t *)"Tox phone "_USERAGENT, - sizeof("Tox phone "_USERAGENT)); - free(_bin_string); - - if ( _number >= 0) { - INFO("Added friend as %d", _number ); - av_allocate_friend(_phone, _number, 0); - } else - INFO("Unknown error %i", _number ); - - return _number; -} - -int av_connect_to_dht(av_session_t *_phone, char *_dht_key, const char *_dht_addr, unsigned short _dht_port) -{ - unsigned char *_binary_string = hex_string_to_bin(_dht_key); - - uint16_t _port = htons(_dht_port); - - int _if = tox_bootstrap_from_address(_phone->_messenger, _dht_addr, 1, _port, _binary_string ); - - free(_binary_string); - - return _if ? 0 : -1; -} - -/*********************************/ - -void do_phone ( av_session_t *_phone ) -{ - INFO("Welcome to tox_phone version: " _USERAGENT "\n" - "Usage: \n" - "f [pubkey] (add friend)\n" - "c [a/v] (type) [friend] (friend id) (calls friend if online)\n" - "h (if call is active hang up)\n" - "a [a/v] (answer incoming call: a - audio / v - audio + video (audio is default))\n" - "r (reject incoming call)\n" - "q (quit)\n" - "================================================================================" - ); - - while ( 1 ) { - char _line [ 1500 ]; - int _len; - - if ( -1 == getinput(_line, 1500, &_len) ) { - printf(" >> "); - fflush(stdout); - continue; - } - - if ( _len > 1 && _line[1] != ' ' && _line[1] != '\n' ) { - INFO("Invalid input!"); - continue; - } - - switch (_line[0]) { - - case 'f': { - char _id [128]; - strncpy(_id, _line + 2, 128); - - av_add_friend(_phone, _id); - - } - break; - - case 'c': { - ToxAvCallType _ctype; - - if ( _len < 5 ) { - INFO("Invalid input; usage: c a/v [friend]"); - break; - } else if ( _line[2] == 'a' || _line[2] != 'v' ) { /* default and audio */ - _ctype = TypeAudio; - } else { /* video */ - _ctype = TypeVideo; - } - - char *_end; - int _friend = strtol(_line + 4, &_end, 10); - - if ( *_end ) { - INFO("Friend num has to be numerical value"); - break; - } - - if ( toxav_call(_phone->av, _friend, _ctype, 30) == ErrorAlreadyInCall ) { - INFO("Already in a call"); - break; - } else INFO("Calling friend: %d!", _friend); - - } - break; - - case 'h': { - if ( toxav_hangup(_phone->av) == ErrorNoCall ) { - INFO("No call!"); - break; - } else INFO("Hung up..."); - - } - break; - - case 'a': { - ToxAvError rc; - - if ( _len > 1 && _line[2] == 'v' ) { - rc = toxav_answer(_phone->av, TypeVideo); - } else - rc = toxav_answer(_phone->av, TypeAudio); - - if ( rc == ErrorInvalidState ) { - INFO("No call to answer!"); - } - - } - break; - - case 'r': { - if ( toxav_reject(_phone->av, "User action") == ErrorInvalidState ) - INFO("No state to cancel!"); - else INFO("Call Rejected..."); - - } - break; - - case 'q': { - INFO("Quitting!"); - return; - } - - case '\n': { - } - - default: { - } break; - - } - - } -} - -void *tox_poll (void *_messenger_p) -{ - Tox **_messenger = _messenger_p; - - while ( *_messenger ) { - tox_do(*_messenger); - usleep(10000); - } - - pthread_exit(NULL); -} - -int av_wait_dht(av_session_t *_phone, int _wait_seconds, const char *_ip, char *_key, unsigned short _port) -{ - if ( !_wait_seconds ) - return -1; - - int _waited = 0; - - while ( !tox_isconnected(_phone->_messenger) ) { - - if ( -1 == av_connect_to_dht(_phone, _key, _ip, _port) ) { - INFO("Could not connect to: %s", _ip); - av_terminate_session(_phone); - return -1; - } - - if ( _waited >= _wait_seconds ) return 0; - - printf("."); - fflush(stdout); - - _waited ++; - usleep(1000000); - } - - int _r = _wait_seconds - _waited; - return _r ? _r : 1; -} -/* ---------------------- */ - -int print_help ( const char *_name ) -{ - printf ( "Usage: %s [IP] [PORT] [KEY]\n" - "\t[IP] (DHT ip)\n" - "\t[PORT] (DHT port)\n" - "\t[KEY] (DHT public key)\n" - "P.S. Friends and key are stored in ./tox_phone.conf\n" - , _name ); - return 1; -} - -int main ( int argc, char *argv [] ) -{ - if ( argc < 1 || argc < 4 ) - return print_help(argv[0]); - - char *_convertable; - - - const char *_ip = argv[1]; - char *_key = argv[3]; - unsigned short _port = strtol(argv[2], &_convertable, 10); - - if ( *_convertable ) { - printf("Invalid port: cannot convert string to long: %s", _convertable); - return 1; - } - - _phone = av_init_session(); - - assert ( _phone ); - - tox_callback_friend_request(_phone->_messenger, av_friend_requ, _phone); - tox_callback_status_message(_phone->_messenger, av_friend_active, _phone); - - - INFO("\r================================================================================\n" - "[!] Trying dht@%s:%d" - , _ip, _port); - - /* Start tox protocol */ - event.rise( tox_poll, &_phone->_messenger ); - - /* Just clean one line */ - printf("\r \r"); - fflush(stdout); - - int _r; - int _wait_seconds = 5; - - for ( _r = 0; _r == 0; _r = av_wait_dht(_phone, _wait_seconds, _ip, _key, _port) ) _wait_seconds --; - - - if ( -1 == _r ) { - INFO("Error while connecting to dht: %s:%d", _ip, _port); - av_terminate_session(_phone); - return 1; - } - - INFO("CONNECTED!\n" - "================================================================================\n" - "%s\n" - "================================================================================" - , trim_spaces(_phone->_my_public_id) ); - - - do_phone (_phone); - - av_terminate_session(_phone); - - return 0; -} diff --git a/toxav/rtp.c b/toxav/rtp.c index b52840c1..a404202b 100755 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -25,6 +25,8 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ +#include "../toxcore/logger.h" + #include "rtp.h" #include #include @@ -227,6 +229,7 @@ static const uint32_t payload_table[] = { RTPHeader *extract_header ( const uint8_t *payload, int length ) { if ( !payload || !length ) { + LOGGER_WARNING("No payload to extract!"); return NULL; } @@ -245,6 +248,7 @@ RTPHeader *extract_header ( const uint8_t *payload, int length ) if ( GET_FLAG_VERSION(_retu) != RTP_VERSION ) { /* Deallocate */ + LOGGER_WARNING("Invalid version!"); free(_retu); return NULL; } @@ -258,6 +262,7 @@ RTPHeader *extract_header ( const uint8_t *payload, int length ) if ( length < _length ) { /* Deallocate */ + LOGGER_WARNING("Length invalid!"); free(_retu); return NULL; } @@ -304,6 +309,7 @@ RTPExtHeader *extract_ext_header ( const uint8_t *payload, uint16_t length ) if ( length < ( _ext_length * sizeof(uint32_t) ) ) { + LOGGER_WARNING("Length invalid!"); free(_retu); return NULL; } @@ -443,6 +449,7 @@ RTPMessage *msg_parse ( uint16_t sequnum, const uint8_t *data, int length ) _retu->header = extract_header ( data, length ); /* It allocates memory and all */ if ( !_retu->header ) { + LOGGER_WARNING("Header failed to extract!"); free(_retu); return NULL; } @@ -461,6 +468,7 @@ RTPMessage *msg_parse ( uint16_t sequnum, const uint8_t *data, int length ) _retu->length -= ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); _from_pos += ( 4 /* Minimum ext header len */ + _retu->ext_header->length * size_32 ); } else { /* Error */ + LOGGER_WARNING("Ext Header failed to extract!"); rtp_free_msg(NULL, _retu); return NULL; } @@ -471,6 +479,7 @@ RTPMessage *msg_parse ( uint16_t sequnum, const uint8_t *data, int length ) if ( length - _from_pos <= MAX_RTP_SIZE ) memcpy ( _retu->data, data + _from_pos, length - _from_pos ); else { + LOGGER_WARNING("Invalid length!"); rtp_free_msg(NULL, _retu); return NULL; } @@ -495,9 +504,16 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l { RTPSession *_session = object; RTPMessage *_msg; - - if ( !_session || length < 13 + crypto_secretbox_MACBYTES) /* 12 is the minimum length for rtp + desc. byte */ + + if ( !_session || length < 13 + crypto_secretbox_MACBYTES) { /* 12 is the minimum length for rtp + desc. byte */ + LOGGER_WARNING("No session or invalid length of received buffer!"); + return -1; + } + + if ( _session->queue_limit <= _session->queue_size ) { + LOGGER_WARNING("Queue limit reached!"); return -1; + } uint8_t _plain[MAX_UDP_PACKET_SIZE]; @@ -510,8 +526,7 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l increase_nonce ( _calculated, _sequnum ); /* Decrypt message */ - int _decrypted_length = decrypt_data_symmetric( - (uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); + int _decrypted_length = decrypt_data_symmetric((uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); /* This packet is either not encrypted properly or late */ @@ -524,7 +539,10 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l _decrypted_length = decrypt_data_symmetric( (uint8_t *)_session->decrypt_key, _session->nonce_cycle, data + 3, length - 3, _plain ); - if ( _decrypted_length == -1 ) return -1; /* This packet is not encrypted properly */ + if ( _decrypted_length == -1 ) { + LOGGER_WARNING("Packet not ecrypted properly!"); + return -1; /* This packet is not encrypted properly */ + } /* Otherwise, if decryption is ok with new cycle, set new cycle */ @@ -533,7 +551,10 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l _decrypted_length = decrypt_data_symmetric( (uint8_t *)_session->decrypt_key, _calculated, data + 3, length - 3, _plain ); - if ( _decrypted_length == -1 ) return -1; /* This is just an error */ + if ( _decrypted_length == -1 ) { + LOGGER_WARNING("Error decrypting!"); + return -1; /* This is just an error */ + } /* A new cycle setting. */ memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES); @@ -543,7 +564,10 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l _msg = msg_parse ( _sequnum, _plain, _decrypted_length ); - if ( !_msg ) return -1; + if ( !_msg ) { + LOGGER_WARNING("Could not parse message!"); + return -1; + } /* Hopefully this goes well * NOTE: Is this even used? @@ -565,6 +589,8 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l _session->last_msg = _session->oldest_msg = _msg; } + _session->queue_size++; + pthread_mutex_unlock(&_session->mutex); return 0; @@ -584,8 +610,10 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l */ RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t length ) { - if ( !session ) + if ( !session ) { + LOGGER_WARNING("No session!"); return NULL; + } uint8_t *_from_pos; RTPMessage *_retu = calloc(1, sizeof (RTPMessage)); @@ -665,6 +693,7 @@ RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t int rtp_release_session_recv ( RTPSession *session ) { if ( !session ) { + LOGGER_WARNING("No session!"); return -1; } @@ -678,13 +707,39 @@ int rtp_release_session_recv ( RTPSession *session ) } session->last_msg = session->oldest_msg = NULL; - + session->queue_size = 0; + pthread_mutex_unlock(&session->mutex); return 0; } +/** + * @brief Call this to change queue limit + * + * @param session The session + * @param limit new limit + * @return void + */ +void rtp_queue_adjust_limit(RTPSession* session, uint64_t limit) +{ + RTPMessage *_tmp, * _it; + pthread_mutex_lock(&session->mutex); + + for ( _it = session->oldest_msg; session->queue_size > limit; _it = _tmp ) { + _tmp = _it->next; + rtp_free_msg( session, _it); + session->queue_size --; + } + + session->oldest_msg = _it; + session->queue_limit = limit; + + pthread_mutex_unlock(&session->mutex); +} + + /** * @brief Gets oldest message in the list. * @@ -694,15 +749,21 @@ int rtp_release_session_recv ( RTPSession *session ) */ RTPMessage *rtp_recv_msg ( RTPSession *session ) { - if ( !session ) + if ( !session ) { + LOGGER_WARNING("No session!"); return NULL; - - RTPMessage *_retu = session->oldest_msg; - + } + + if ( session->queue_size == 0 ) { + return NULL; + } + pthread_mutex_lock(&session->mutex); + + RTPMessage *_retu = session->oldest_msg; - if ( _retu ) - session->oldest_msg = _retu->next; + /*if (_retu)*/ + session->oldest_msg = _retu->next; if ( !session->oldest_msg ) session->last_msg = NULL; @@ -728,7 +789,10 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat { RTPMessage *msg = rtp_new_message (session, data, length); - if ( !msg ) return -1; + if ( !msg ) { + LOGGER_WARNING("No session!"); + return -1; + } uint8_t _send_data [ MAX_UDP_PACKET_SIZE ]; @@ -749,9 +813,8 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat _send_data[2] = msg->data[1]; - /*if ( full_length != sendpacket ( messenger->net, *((IP_Port*) &session->dest), _send_data, full_length) ) {*/ if ( full_length != send_custom_user_packet(messenger, session->dest, _send_data, full_length) ) { - /*fprintf(stderr, "Rtp error: %s\n", strerror(errno));*/ + LOGGER_WARNING("Failed to send full packet! std error: %s", strerror(errno)); rtp_free_msg ( session, msg ); return -1; } @@ -822,9 +885,10 @@ RTPSession *rtp_init_session ( int payload_type, RTPSession *_retu = calloc(1, sizeof(RTPSession)); assert(_retu); - /*networking_registerhandler(messenger->net, payload_type, rtp_handle_packet, _retu);*/ - if ( -1 == custom_user_packet_registerhandler(messenger, friend_num, payload_type, rtp_handle_packet, _retu) ) { - /*fprintf(stderr, "Error setting custom register handler for rtp session\n");*/ + if ( -1 == custom_user_packet_registerhandler(messenger, friend_num, payload_type, rtp_handle_packet, _retu) || + !encrypt_key, !decrypt_key, !encrypt_nonce, !decrypt_nonce + ) { + LOGGER_ERROR("Error setting custom register handler for rtp session"); free(_retu); return NULL; } @@ -843,9 +907,7 @@ RTPSession *rtp_init_session ( int payload_type, _retu->rsequnum = _retu->sequnum = 1; _retu->ext_header = NULL; /* When needed allocate */ - _retu->framerate = -1; - _retu->resolution = -1; - + _retu->encrypt_key = encrypt_key; _retu->decrypt_key = decrypt_key; @@ -870,6 +932,8 @@ RTPSession *rtp_init_session ( int payload_type, _retu->prefix = payload_type; _retu->oldest_msg = _retu->last_msg = NULL; + _retu->queue_limit = 100; /* Default */ + _retu->queue_size = 0; pthread_mutex_init(&_retu->mutex, NULL); /* @@ -890,8 +954,10 @@ RTPSession *rtp_init_session ( int payload_type, */ int rtp_terminate_session ( RTPSession *session, Messenger *messenger ) { - if ( !session ) + if ( !session ) { + LOGGER_WARNING("No session!"); return -1; + } custom_user_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL); diff --git a/toxav/rtp.h b/toxav/rtp.h index 58b16ab1..4d66e791 100755 --- a/toxav/rtp.h +++ b/toxav/rtp.h @@ -108,11 +108,7 @@ typedef struct _RTPSession { */ RTPExtHeader *ext_header; - /* External header identifiers */ - int resolution; - int framerate; - - + /* Since these are only references of the * call structure don't allocate or free */ @@ -126,6 +122,9 @@ typedef struct _RTPSession { RTPMessage *oldest_msg; RTPMessage *last_msg; /* tail */ + + uint64_t queue_limit;/* Default 100; modify per thy liking */ + uint64_t queue_size; /* currently holding << messages */ /* Msg prefix for core to know when recving */ uint8_t prefix; @@ -147,6 +146,15 @@ typedef struct _RTPSession { int rtp_release_session_recv ( RTPSession *session ); +/** + * @brief Call this to change queue limit + * + * @param session The session + * @param limit new limit + * @return void + */ +void rtp_queue_adjust_limit ( RTPSession *session, uint64_t limit ); + /** * @brief Get's oldest message in the list. * @@ -195,7 +203,7 @@ void rtp_free_msg ( RTPSession *session, RTPMessage *msg ); * @retval NULL Error occurred. */ RTPSession *rtp_init_session ( int payload_type, - Messenger *messenger, + Messenger *messenger, int friend_num, const uint8_t *encrypt_key, const uint8_t *decrypt_key, diff --git a/toxav/toxav.c b/toxav/toxav.c index f1ff2312..0301c6b2 100755 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -105,7 +105,7 @@ ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings, uint32_t m av->msi_session = msi_init_session(av->messenger, max_calls); av->msi_session->agent_handler = av; - av->rtp_sessions = calloc(sizeof(RTPSession), max_calls); + av->rtp_sessions = calloc(sizeof(CallRTPSessions), max_calls); av->max_calls = max_calls; av->j_buf = create_queue(codec_settings->jbuf_capacity); @@ -288,8 +288,9 @@ int toxav_stop_call ( ToxAv* av, uint32_t call_index ) */ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_video ) { - if ( !av->msi_session || !av->msi_session->calls[call_index] ) { - return ErrorNoCall; + if ( !av->msi_session || av->msi_session->max_calls <= call_index || !av->msi_session->calls[call_index] ) { + /*fprintf(stderr, "Error while starting audio RTP session: invalid call!\n");*/ + return ErrorInternal; } av->rtp_sessions[call_index].crtps[audio_index] = @@ -305,10 +306,11 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid if ( !av->rtp_sessions[call_index].crtps[audio_index] ) { - fprintf(stderr, "Error while starting audio RTP session!\n"); + /*fprintf(stderr, "Error while starting audio RTP session!\n");*/ return ErrorStartingAudioRtp; } - + + if ( support_video ) { av->rtp_sessions[call_index].crtps[video_index] = rtp_init_session ( @@ -323,10 +325,12 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid if ( !av->rtp_sessions[call_index].crtps[video_index] ) { - fprintf(stderr, "Error while starting video RTP session!\n"); + /*fprintf(stderr, "Error while starting video RTP session!\n");*/ return ErrorStartingVideoRtp; } } + + return ErrorNone; } @@ -341,12 +345,12 @@ int toxav_prepare_transmission ( ToxAv* av, uint32_t call_index, int support_vid int toxav_kill_transmission ( ToxAv *av, uint32_t call_index ) { if ( av->rtp_sessions[call_index].crtps[audio_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[audio_index], av->messenger) ) { - fprintf(stderr, "Error while terminating audio RTP session!\n"); + /*fprintf(stderr, "Error while terminating audio RTP session!\n");*/ return ErrorTerminatingAudioRtp; } if ( av->rtp_sessions[call_index].crtps[video_index] && -1 == rtp_terminate_session(av->rtp_sessions[call_index].crtps[video_index], av->messenger) ) { - fprintf(stderr, "Error while terminating video RTP session!\n"); + /*fprintf(stderr, "Error while terminating video RTP session!\n");*/ return ErrorTerminatingVideoRtp; } @@ -441,13 +445,15 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou uint8_t packet [RTP_PAYLOAD_SIZE]; int recved_size = 0; - int error; + int rc; do { recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); - if (recved_size > 0 && ( error = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) - fprintf(stderr, "Error decoding: %s\n", vpx_codec_err_to_string(error)); + if (recved_size > 0 && ( rc = vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0) ) != VPX_CODEC_OK) { + /*fprintf(stderr, "Error decoding video: %s\n", vpx_codec_err_to_string(rc));*/ + return ErrorInternal; + } } while (recved_size > 0); @@ -472,8 +478,9 @@ inline__ int toxav_recv_video ( ToxAv *av, uint32_t call_index, vpx_image_t **ou */ inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *input) { - if (vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US) != VPX_CODEC_OK) { - fprintf(stderr, "Could not encode video frame\n"); + int rc = vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); + if ( rc != VPX_CODEC_OK) { + /*fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));*/ return ErrorInternal; } @@ -491,11 +498,40 @@ inline__ int toxav_send_video ( ToxAv *av, uint32_t call_index, vpx_image_t *inp } if (sent > 0) - return 0; + return ErrorNone; return ErrorInternal; } +int toxav_prepare_video_frame(ToxAv* av, uint8_t* dest, int dest_max, vpx_image_t* input) +{ + int rc = vpx_codec_encode(&av->cs->v_encoder, input, av->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); + if ( rc != VPX_CODEC_OK) { + /*fprintf(stderr, "Could not encode video frame: %s\n", vpx_codec_err_to_string(rc));*/ + return ErrorInternal; + } + ++av->cs->frame_counter; + + vpx_codec_iter_t iter = NULL; + const vpx_codec_cx_pkt_t *pkt; + int counted = 0, copied = 0; + + while ( (pkt = vpx_codec_get_cx_data(&av->cs->v_encoder, &iter)) ) { + if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { + + if ( copied + pkt->data.frame.sz > dest_max ) return ErrorPacketTooLarge; + + mempcpy(dest + copied, pkt->data.frame.buf, pkt->data.frame.sz); + + if (toxav_send_rtp_payload(av, call_index, TypeVideo, pkt->data.frame.buf, pkt->data.frame.sz) != -1) + ++counted; + } + } + + if (counted > 0) + return ErrorNone; +} + /** * @brief Receive decoded audio frame. * @@ -517,16 +553,22 @@ inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size, int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet); if ( recved_size == ErrorAudioPacketLost ) { - return opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); + int dec_size = opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1); + + if ( dec_size != OPUS_OK ) return ErrorInternal; + } else if ( recved_size ) { - return opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); + int dec_size = opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0); + + if ( dec_size != OPUS_OK ) return ErrorInternal; + } else { return 0; /* Nothing received */ } } /** - * @brief Encode and send audio frame. + * @brief Send audio frame. * * @param av Handler. * @param frame The frame (raw 16 bit signed pcm with AUDIO_CHANNELS channels audio.) @@ -538,13 +580,29 @@ inline__ int toxav_recv_audio ( ToxAv *av, uint32_t call_index, int frame_size, */ inline__ int toxav_send_audio ( ToxAv *av, uint32_t call_index, const int16_t *frame, int frame_size) { - uint8_t temp_data[RTP_PAYLOAD_SIZE]; - int32_t ret = opus_encode(av->cs->audio_encoder, frame, frame_size, temp_data, sizeof(temp_data)); + return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size); +} - if (ret <= 0) +/** + * @brief Encode audio frame + * + * @param av Handler + * @param dest dest + * @param dest_max Max dest size + * @param frame The frame + * @param frame_size The frame size + * @return int + * @retval ToxAvError On error. + * @retval >0 On success + */ +int toxav_prepare_audio_frame ( ToxAv* av, int16_t* dest, int dest_max, const int16_t* frame, int frame_size) +{ + int32_t rc = opus_encode(av->cs->audio_encoder, frame, frame_size, dest, dest_max); + + if (rc <= 0) return ErrorInternal; - - return toxav_send_rtp_payload(av, call_index, TypeAudio, temp_data, ret); + + return rc; } /** @@ -598,12 +656,27 @@ inline__ int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capabilit } /** - * @brief Get messenger handle + * @brief Set queue limit * - * @param av Handler. - * @return Tox* + * @param av Handler + * @param call_index index + * @param limit the limit + * @return void + */ +void toxav_set_audio_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) +{ + rtp_queue_adjust_limit(av->rtp_sessions[call_index].crtps[audio_index], limit); +} + +/** + * @brief Set queue limit + * + * @param av Handler + * @param call_index index + * @param limit the limit + * @return void */ -inline__ Tox* toxav_get_tox ( ToxAv* av ) +void toxav_set_video_queue_limit(ToxAv* av, uint32_t call_index, uint64_t limit) { - return (Tox*)av->messenger; + rtp_queue_adjust_limit(av->rtp_sessions[call_index].crtps[video_index], limit); } diff --git a/toxav/toxav.h b/toxav/toxav.h index 89addb2b..5a8e8f56 100755 --- a/toxav/toxav.h +++ b/toxav/toxav.h @@ -87,7 +87,8 @@ typedef enum { ErrorStartingVideoRtp = -8 , /* Error in toxav_prepare_transmission() */ ErrorTerminatingAudioRtp = -9, /* Returned in toxav_kill_transmission() */ ErrorTerminatingVideoRtp = -10, /* Returned in toxav_kill_transmission() */ - + ErrorPacketTooLarge = -11, /* Buffer exceeds size while encoding */ + } ToxAvError; @@ -276,7 +277,7 @@ int toxav_recv_audio( ToxAv* av, uint32_t call_index, int frame_size, int16_t* d int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input); /** - * @brief Encode and send audio frame. + * @brief Send audio frame. * * @param av Handler. * @param frame The frame (raw 16 bit signed pcm with AUDIO_CHANNELS channels audio.) @@ -288,6 +289,22 @@ int toxav_send_video ( ToxAv* av, uint32_t call_index, vpx_image_t* input); */ int toxav_send_audio ( ToxAv* av, uint32_t call_index, const int16_t* frame, int frame_size); +int toxav_prepare_video_frame ( ToxAv* av, uint8_t* dest, int dest_max, vpx_image_t* input ); + +/** + * @brief Encode audio frame + * + * @param av Handler + * @param dest dest + * @param dest_max Max dest size + * @param frame The frame + * @param frame_size The frame size + * @return int + * @retval ToxAvError On error. + * @retval >0 On success + */ +int toxav_prepare_audio_frame ( ToxAv* av, int16_t* dest, int dest_max, const int16_t* frame, int frame_size); + /** * @brief Get peer transmission type. It can either be audio or video. * @@ -320,11 +337,23 @@ int toxav_get_peer_id ( ToxAv* av, uint32_t call_index, int peer ); int toxav_capability_supported ( ToxAv* av, ToxAvCapabilities capability ); /** - * @brief Get messenger handle + * @brief Set queue limit * - * @param av Handler. - * @return Tox* + * @param av Handler + * @param call_index index + * @param limit the limit + * @return void + */ +void toxav_set_audio_queue_limit ( ToxAv* av, uint32_t call_index, uint64_t limit ); + +/** + * @brief Set queue limit + * + * @param av Handler + * @param call_index index + * @param limit the limit + * @return void */ -Tox* toxav_get_tox ( ToxAv* av ); +void toxav_set_video_queue_limit ( ToxAv* av, uint32_t call_index, uint64_t limit ); #endif /* __TOXAV */ \ No newline at end of file -- cgit v1.2.3