mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge pull request #789 from mannol1/master
Fixed several bugs and added some features
This commit is contained in:
commit
b451565f17
|
@ -487,7 +487,8 @@ fi
|
|||
if test "x$BUILD_AV" = "xyes"; then
|
||||
# toxcore lib needs an global?
|
||||
# So far this works okay
|
||||
AV_LIBS="$OPUS_LIBS $VPX_LIBS"
|
||||
## What about pthread?
|
||||
AV_LIBS="$OPUS_LIBS $VPX_LIBS -pthread"
|
||||
AC_SUBST(AV_LIBS)
|
||||
|
||||
AV_CFLAGS="$OPUS_CFLAGS $VPX_CFLAGS"
|
||||
|
|
11
libtoxav.pc
Normal file
11
libtoxav.pc
Normal file
|
@ -0,0 +1,11 @@
|
|||
prefix=/usr/local
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: libtoxav
|
||||
Description: Tox A/V library
|
||||
Requires:
|
||||
Version: 0.0.0
|
||||
Libs: -L${libdir} -ltoxav -lopus -lvpx -lm -pthread
|
||||
Cflags: -I${includedir}
|
107
toxav/media.c
107
toxav/media.c
|
@ -46,18 +46,28 @@ struct jitter_buffer {
|
|||
uint8_t id_set;
|
||||
};
|
||||
|
||||
int empty_queue(struct jitter_buffer *q)
|
||||
{
|
||||
while (q->size > 0) {
|
||||
rtp_free_msg(NULL, q->queue[q->front]);
|
||||
q->front++;
|
||||
|
||||
if (q->front == q->capacity)
|
||||
q->front = 0;
|
||||
|
||||
q->size--;
|
||||
}
|
||||
|
||||
q->id_set = 0;
|
||||
q->queue_ready = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct jitter_buffer *create_queue(int capacity)
|
||||
{
|
||||
struct jitter_buffer *q;
|
||||
q = (struct jitter_buffer *)calloc(sizeof(struct jitter_buffer), 1);
|
||||
q->queue = (RTPMessage **)calloc(sizeof(RTPMessage *), capacity);
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < capacity; ++i) {
|
||||
q->queue[i] = NULL;
|
||||
}
|
||||
|
||||
q = calloc(sizeof(struct jitter_buffer), 1);
|
||||
q->queue = calloc(sizeof(RTPMessage *), capacity);
|
||||
q->size = 0;
|
||||
q->capacity = capacity;
|
||||
q->front = 0;
|
||||
|
@ -81,7 +91,7 @@ uint8_t sequence_number_older(uint16_t sn_a, uint16_t sn_b, uint32_t ts_a, uint3
|
|||
/* 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)
|
||||
{
|
||||
if (q->size == 0 || q->queue_ready == 0) {
|
||||
if (q->size == 0 || q->queue_ready == 0) { /* Empty queue */
|
||||
q->queue_ready = 0;
|
||||
*success = 0;
|
||||
return NULL;
|
||||
|
@ -103,13 +113,13 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success)
|
|||
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);
|
||||
/*printf("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");
|
||||
/*printf("packet too old\n");*/
|
||||
*success = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -128,27 +138,12 @@ RTPMessage *dequeue(struct jitter_buffer *q, int *success)
|
|||
return q->queue[front];
|
||||
}
|
||||
|
||||
int empty_queue(struct jitter_buffer *q)
|
||||
{
|
||||
while (q->size > 0) {
|
||||
q->size--;
|
||||
rtp_free_msg(NULL, q->queue[q->front]);
|
||||
q->front++;
|
||||
|
||||
if (q->front == q->capacity)
|
||||
q->front = 0;
|
||||
}
|
||||
|
||||
q->id_set = 0;
|
||||
q->queue_ready = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int queue(struct jitter_buffer *q, RTPMessage *pk)
|
||||
{
|
||||
if (q->size == q->capacity) {
|
||||
printf("buffer full, emptying buffer...\n");
|
||||
if (q->size == q->capacity) { /* Full, empty queue */
|
||||
empty_queue(q);
|
||||
/*rtp_free_msg(NULL, pk);*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -180,7 +175,7 @@ int queue(struct jitter_buffer *q, RTPMessage *pk)
|
|||
temp = q->queue[a];
|
||||
q->queue[a] = q->queue[b];
|
||||
q->queue[b] = temp;
|
||||
printf("had to swap\n");
|
||||
/*printf("had to swap\n");*/
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -229,7 +224,7 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
|
|||
int res = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
|
||||
|
||||
if (res) {
|
||||
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
fprintf(stderr, "Failed to get config: %s\n", vpx_codec_err_to_string(res));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -266,49 +261,43 @@ CodecState *codec_init_session ( uint32_t audio_bitrate,
|
|||
uint16_t video_height,
|
||||
uint32_t video_bitrate )
|
||||
{
|
||||
CodecState *_retu = calloc(sizeof(CodecState), 1);
|
||||
assert(_retu);
|
||||
CodecState *retu = calloc(sizeof(CodecState), 1);
|
||||
assert(retu);
|
||||
|
||||
_retu->audio_bitrate = audio_bitrate;
|
||||
_retu->audio_sample_rate = audio_sample_rate;
|
||||
retu->audio_bitrate = audio_bitrate;
|
||||
retu->audio_sample_rate = audio_sample_rate;
|
||||
|
||||
/* Encoders */
|
||||
if (!video_width || !video_height) {
|
||||
video_width = 320;
|
||||
video_height = 240;
|
||||
if (!video_width || !video_height) { /* Disable video */
|
||||
/*video_width = 320;
|
||||
video_height = 240; */
|
||||
}
|
||||
else {
|
||||
retu->supported_actions |= ( 0 == init_video_encoder(retu, video_width, video_height, video_bitrate) ) ? v_encoding : 0;
|
||||
retu->supported_actions |= ( 0 == init_video_decoder(retu) ) ? v_decoding : 0;
|
||||
}
|
||||
|
||||
if ( 0 == init_video_encoder(_retu, video_width, video_height, video_bitrate) )
|
||||
printf("Video encoder initialized!\n");
|
||||
retu->supported_actions |= ( 0 == init_audio_encoder(retu, audio_channels) ) ? a_encoding : 0;
|
||||
retu->supported_actions |= ( 0 == init_audio_decoder(retu, audio_channels) ) ? a_decoding : 0;
|
||||
|
||||
if ( 0 == init_audio_encoder(_retu, audio_channels) )
|
||||
printf("Audio encoder initialized!\n");
|
||||
|
||||
|
||||
/* Decoders */
|
||||
if ( 0 == init_video_decoder(_retu) )
|
||||
printf("Video decoder initialized!\n");
|
||||
|
||||
if ( 0 == init_audio_decoder(_retu, audio_channels) )
|
||||
printf("Audio decoder initialized!\n");
|
||||
|
||||
|
||||
return _retu;
|
||||
return retu;
|
||||
}
|
||||
|
||||
void codec_terminate_session ( CodecState *cs )
|
||||
{
|
||||
if ( cs->audio_encoder ) {
|
||||
if ( cs->audio_encoder )
|
||||
opus_encoder_destroy(cs->audio_encoder);
|
||||
printf("Terminated encoder!\n");
|
||||
}
|
||||
|
||||
if ( cs->audio_decoder ) {
|
||||
if ( cs->audio_decoder )
|
||||
opus_decoder_destroy(cs->audio_decoder);
|
||||
printf("Terminated decoder!\n");
|
||||
}
|
||||
|
||||
/* TODO: Terminate video */
|
||||
|
||||
/* TODO: Terminate video
|
||||
* Do what???
|
||||
*/
|
||||
if ( cs->supported_actions & v_decoding )
|
||||
vpx_codec_destroy(&cs->v_decoder);
|
||||
|
||||
if ( cs->supported_actions & v_encoding )
|
||||
vpx_codec_destroy(&cs->v_encoder);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,14 @@
|
|||
/* Audio encoding/decoding */
|
||||
#include <opus/opus.h>
|
||||
|
||||
enum _actions
|
||||
{
|
||||
no_actions,
|
||||
a_encoding = 1 << 0,
|
||||
a_decoding = 1 << 1,
|
||||
v_encoding = 1 << 2,
|
||||
v_decoding = 1 << 3
|
||||
};
|
||||
|
||||
typedef struct _CodecState {
|
||||
|
||||
|
@ -56,12 +64,13 @@ typedef struct _CodecState {
|
|||
/* audio decoding */
|
||||
OpusDecoder *audio_decoder;
|
||||
|
||||
uint64_t supported_actions; /* Encoding decoding etc */
|
||||
|
||||
} CodecState;
|
||||
|
||||
typedef struct _RTPMessage RTPMessage;
|
||||
|
||||
struct jitter_buffer *create_queue(int capacity);
|
||||
int empty_queue(struct jitter_buffer *q);
|
||||
|
||||
int queue(struct jitter_buffer *q, RTPMessage *pk);
|
||||
RTPMessage *dequeue(struct jitter_buffer *q, int *success);
|
||||
|
|
82
toxav/msi.c
Normal file → Executable file
82
toxav/msi.c
Normal file → Executable file
|
@ -616,10 +616,15 @@ int send_message ( MSISession *session, MSIMessage *msg, uint32_t to )
|
|||
void flush_peer_type ( MSISession *session, MSIMessage *msg, int peer_id )
|
||||
{
|
||||
if ( msg->calltype.header_value ) {
|
||||
if ( strcmp ( ( const char * ) msg->calltype.header_value, CT_AUDIO_HEADER_VALUE ) == 0 ) {
|
||||
uint8_t hdrval [MSI_MAXMSG_SIZE]; /* Make sure no overflow */
|
||||
|
||||
memcpy(hdrval, msg->calltype.header_value, msg->calltype.size);
|
||||
hdrval[msg->calltype.size] = '\0';
|
||||
|
||||
if ( strcmp ( ( const char * ) hdrval, CT_AUDIO_HEADER_VALUE ) == 0 ) {
|
||||
session->call->type_peer[peer_id] = type_audio;
|
||||
|
||||
} else if ( strcmp ( ( const char * ) msg->calltype.header_value, CT_VIDEO_HEADER_VALUE ) == 0 ) {
|
||||
} else if ( strcmp ( ( const char * ) hdrval, CT_VIDEO_HEADER_VALUE ) == 0 ) {
|
||||
session->call->type_peer[peer_id] = type_video;
|
||||
} else {} /* Error */
|
||||
} else {} /* Error */
|
||||
|
@ -670,7 +675,7 @@ int handle_error ( MSISession *session, MSICallError errid, uint32_t to )
|
|||
session->last_error_id = errid;
|
||||
session->last_error_str = stringify_error ( errid );
|
||||
|
||||
event.rise ( callbacks[MSI_OnError], session->agent_handler );
|
||||
if ( callbacks[MSI_OnError] ) event.rise ( callbacks[MSI_OnError], session->agent_handler );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -723,12 +728,12 @@ void *handle_timeout ( void *arg )
|
|||
uint16_t _it = 0;
|
||||
|
||||
for ( ; _it < _peer_count; _it++ )
|
||||
msi_cancel ( arg, _peers[_it], (const uint8_t *)"Timeout" );
|
||||
msi_cancel ( arg, _peers[_it], "Timeout" );
|
||||
|
||||
}
|
||||
|
||||
( *callbacks[MSI_OnRequestTimeout] ) ( _session->agent_handler );
|
||||
( *callbacks[MSI_OnEnding ] ) ( _session->agent_handler );
|
||||
if ( callbacks[MSI_OnRequestTimeout] ) callbacks[MSI_OnRequestTimeout] ( _session->agent_handler );
|
||||
if ( callbacks[MSI_OnEnding] ) callbacks[MSI_OnEnding ] ( _session->agent_handler );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -864,7 +869,7 @@ int handle_recv_invite ( MSISession *session, MSIMessage *msg )
|
|||
send_message ( session, _msg_ringing, msg->friend_id );
|
||||
free_message ( _msg_ringing );
|
||||
|
||||
event.rise ( callbacks[MSI_OnInvite], session->agent_handler );
|
||||
if ( callbacks[MSI_OnInvite] ) event.rise ( callbacks[MSI_OnInvite], session->agent_handler );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -888,7 +893,7 @@ int handle_recv_start ( MSISession *session, MSIMessage *msg )
|
|||
|
||||
flush_peer_type ( session, msg, 0 );
|
||||
|
||||
event.rise ( callbacks[MSI_OnStart], session->agent_handler );
|
||||
if ( callbacks[MSI_OnStart] ) event.rise ( callbacks[MSI_OnStart], session->agent_handler );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -905,7 +910,7 @@ int handle_recv_reject ( MSISession *session, MSIMessage *msg )
|
|||
free_message ( _msg_end );
|
||||
|
||||
event.timer_release ( session->call->request_timer_id );
|
||||
event.rise ( callbacks[MSI_OnReject], session->agent_handler );
|
||||
if ( callbacks[MSI_OnReject] ) event.rise ( callbacks[MSI_OnReject], session->agent_handler );
|
||||
session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout );
|
||||
|
||||
return 1;
|
||||
|
@ -920,7 +925,7 @@ int handle_recv_cancel ( MSISession *session, MSIMessage *msg )
|
|||
|
||||
terminate_call ( session );
|
||||
|
||||
event.rise ( callbacks[MSI_OnCancel], session->agent_handler );
|
||||
if ( callbacks[MSI_OnCancel] ) event.rise ( callbacks[MSI_OnCancel], session->agent_handler );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -938,7 +943,7 @@ int handle_recv_end ( MSISession *session, MSIMessage *msg )
|
|||
|
||||
terminate_call ( session );
|
||||
|
||||
event.rise ( callbacks[MSI_OnEnd], session->agent_handler );
|
||||
if ( callbacks[MSI_OnEnd] ) event.rise ( callbacks[MSI_OnEnd], session->agent_handler );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -952,7 +957,7 @@ int handle_recv_ringing ( MSISession *session, MSIMessage *msg )
|
|||
return 0;
|
||||
|
||||
session->call->ringing_timer_id = event.timer_alloc ( handle_timeout, session, session->call->ringing_tout_ms );
|
||||
event.rise ( callbacks[MSI_OnRinging], session->agent_handler );
|
||||
if ( callbacks[MSI_OnRinging] ) event.rise ( callbacks[MSI_OnRinging], session->agent_handler );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -991,7 +996,7 @@ int handle_recv_starting ( MSISession *session, MSIMessage *msg )
|
|||
|
||||
flush_peer_type ( session, msg, 0 );
|
||||
|
||||
event.rise ( callbacks[MSI_OnStarting], session->agent_handler );
|
||||
if ( callbacks[MSI_OnStarting] ) event.rise ( callbacks[MSI_OnStarting], session->agent_handler );
|
||||
event.timer_release ( session->call->ringing_timer_id );
|
||||
|
||||
return 1;
|
||||
|
@ -1003,11 +1008,19 @@ int handle_recv_ending ( MSISession *session, MSIMessage *msg )
|
|||
if ( has_call_error ( session, msg ) == 0 )
|
||||
return 0;
|
||||
|
||||
/* Do the callback before ending
|
||||
if ( callbacks[MSI_OnEnding] ) event.rise ( callbacks[MSI_OnEnding], session->agent_handler );
|
||||
*/
|
||||
|
||||
/* Stop timer */
|
||||
event.timer_release ( session->call->request_timer_id );
|
||||
|
||||
/* Call callback */
|
||||
if ( callbacks[MSI_OnEnding] ) callbacks[MSI_OnEnding](session->agent_handler);
|
||||
|
||||
/* Terminate call */
|
||||
terminate_call ( session );
|
||||
|
||||
event.rise ( callbacks[MSI_OnEnding], session->agent_handler );
|
||||
|
||||
return 1;
|
||||
}
|
||||
int handle_recv_error ( MSISession *session, MSIMessage *msg )
|
||||
|
@ -1023,7 +1036,7 @@ int handle_recv_error ( MSISession *session, MSIMessage *msg )
|
|||
|
||||
terminate_call ( session );
|
||||
|
||||
event.rise ( callbacks[MSI_OnEnding], session->agent_handler );
|
||||
if ( callbacks[MSI_OnEnding] ) event.rise ( callbacks[MSI_OnEnding], session->agent_handler );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1082,7 +1095,12 @@ void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16
|
|||
|
||||
if ( _msg->request.header_value ) { /* Handle request */
|
||||
|
||||
const uint8_t *_request_value = _msg->request.header_value;
|
||||
if ( _msg->response.size > 32 ) goto free_end;
|
||||
|
||||
uint8_t _request_value[32];
|
||||
|
||||
memcpy(_request_value, _msg->request.header_value, _msg->request.size);
|
||||
_request_value[_msg->request.size] = '\0';
|
||||
|
||||
if ( same ( _request_value, stringify_request ( invite ) ) ) {
|
||||
handle_recv_invite ( _session, _msg );
|
||||
|
@ -1100,14 +1118,16 @@ void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16
|
|||
handle_recv_end ( _session, _msg );
|
||||
}
|
||||
|
||||
else {
|
||||
free_message ( _msg );
|
||||
return;
|
||||
}
|
||||
else goto free_end;
|
||||
|
||||
} else if ( _msg->response.header_value ) { /* Handle response */
|
||||
|
||||
const uint8_t *_response_value = _msg->response.header_value;
|
||||
if ( _msg->response.size > 32 ) goto free_end;
|
||||
|
||||
uint8_t _response_value[32];
|
||||
|
||||
memcpy(_response_value, _msg->response.header_value, _msg->response.size);
|
||||
_response_value[_msg->response.size] = '\0';
|
||||
|
||||
if ( same ( _response_value, stringify_response ( ringing ) ) ) {
|
||||
handle_recv_ringing ( _session, _msg );
|
||||
|
@ -1120,10 +1140,8 @@ void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16
|
|||
|
||||
} else if ( same ( _response_value, stringify_response ( error ) ) ) {
|
||||
handle_recv_error ( _session, _msg );
|
||||
} else {
|
||||
free_message ( _msg );
|
||||
return;
|
||||
}
|
||||
|
||||
} else goto free_end;
|
||||
|
||||
/* Got response so cancel timer */
|
||||
if ( _session->call )
|
||||
|
@ -1131,7 +1149,7 @@ void msi_handle_packet ( Messenger *messenger, int source, uint8_t *data, uint16
|
|||
|
||||
}
|
||||
|
||||
free_message ( _msg );
|
||||
free_end:free_message ( _msg );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1286,16 +1304,16 @@ int msi_hangup ( MSISession *session )
|
|||
if ( !session->call || session->call->state != call_active )
|
||||
return -1;
|
||||
|
||||
MSIMessage *_msg_ending = msi_new_message ( TYPE_REQUEST, stringify_request ( end ) );
|
||||
MSIMessage *_msg_end = msi_new_message ( TYPE_REQUEST, stringify_request ( end ) );
|
||||
|
||||
/* hangup for each peer */
|
||||
int _it = 0;
|
||||
|
||||
for ( ; _it < session->call->peer_count; _it ++ )
|
||||
send_message ( session, _msg_ending, session->call->peers[_it] );
|
||||
send_message ( session, _msg_end, session->call->peers[_it] );
|
||||
|
||||
|
||||
free_message ( _msg_ending );
|
||||
free_message ( _msg_end );
|
||||
|
||||
session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout );
|
||||
|
||||
|
@ -1352,13 +1370,13 @@ int msi_answer ( MSISession *session, MSICallType call_type )
|
|||
* @param reason Set optional reason header. Pass NULL if none.
|
||||
* @return int
|
||||
*/
|
||||
int msi_cancel ( MSISession *session, uint32_t peer, const uint8_t *reason )
|
||||
int msi_cancel ( MSISession *session, uint32_t peer, const char *reason )
|
||||
{
|
||||
assert ( session );
|
||||
|
||||
MSIMessage *_msg_cancel = msi_new_message ( TYPE_REQUEST, stringify_request ( cancel ) );
|
||||
|
||||
if ( reason ) msi_msg_set_reason(_msg_cancel, reason, strlen((const char *)reason));
|
||||
if ( reason ) msi_msg_set_reason(_msg_cancel, (const uint8_t*)reason, strlen(reason));
|
||||
|
||||
send_message ( session, _msg_cancel, peer );
|
||||
free_message ( _msg_cancel );
|
||||
|
|
2
toxav/msi.h
Normal file → Executable file
2
toxav/msi.h
Normal file → Executable file
|
@ -206,7 +206,7 @@ int msi_answer ( MSISession *session, MSICallType call_type );
|
|||
* @param reason Set optional reason header. Pass NULL if none.
|
||||
* @return int
|
||||
*/
|
||||
int msi_cancel ( MSISession *session, uint32_t peer, const uint8_t *reason );
|
||||
int msi_cancel ( MSISession* session, uint32_t peer, const char* reason );
|
||||
|
||||
|
||||
/**
|
||||
|
|
170
toxav/phone.c
Normal file → Executable file
170
toxav/phone.c
Normal file → Executable file
|
@ -428,8 +428,8 @@ void *encode_audio_thread(void *arg)
|
|||
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) {
|
||||
|
@ -437,8 +437,7 @@ void *encode_audio_thread(void *arg)
|
|||
|
||||
ret = toxav_send_audio(_phone->av, frame, frame_size);
|
||||
|
||||
if (ret < 0)
|
||||
printf("Could not encode or send audio packet\n");
|
||||
if (ret < 0) printf("Could not encode or send audio packet\n");
|
||||
|
||||
} else {
|
||||
usleep(1000);
|
||||
|
@ -734,6 +733,114 @@ ending:
|
|||
|
||||
|
||||
|
||||
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 )
|
||||
|
@ -742,7 +849,7 @@ int phone_startmedia_loop ( ToxAv *arg )
|
|||
return -1;
|
||||
}
|
||||
|
||||
toxav_prepare_transmission(arg);
|
||||
toxav_prepare_transmission(arg, 1);
|
||||
|
||||
/*
|
||||
* Rise all threads
|
||||
|
@ -759,10 +866,10 @@ int phone_startmedia_loop ( ToxAv *arg )
|
|||
#endif
|
||||
|
||||
/* Always send audio */
|
||||
if ( 0 > event.rise(encode_audio_thread, toxav_get_agent_handler(arg)) ) {
|
||||
/*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 &&
|
||||
|
@ -771,12 +878,19 @@ int phone_startmedia_loop ( ToxAv *arg )
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ( 0 > event.rise(decode_audio_thread, toxav_get_agent_handler(arg)) ) {
|
||||
/*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, toxav_get_agent_handler(arg)) ) {
|
||||
INFO ("Shit-head");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -888,14 +1002,16 @@ void *callback_call_ended ( void *_arg )
|
|||
_phone->running_encvid = 0;
|
||||
_phone->running_decvid = 0;
|
||||
|
||||
/* Wait until all threads are done */
|
||||
/* Wait until all threads are done
|
||||
|
||||
while ( _phone->running_encaud != -1 ||
|
||||
_phone->running_decaud != -1 ||
|
||||
_phone->running_encvid != -1 ||
|
||||
_phone->running_decvid != -1 )
|
||||
|
||||
usleep(10000000);
|
||||
usleep(1000000);*/
|
||||
|
||||
while (_phone->running_decaud != -1) usleep(1000000);
|
||||
|
||||
toxav_kill_transmission(_phone->av);
|
||||
INFO ( "Call ended!" );
|
||||
|
@ -977,7 +1093,7 @@ av_session_t *av_init_session()
|
|||
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;
|
||||
return NULL;
|
||||
goto failed_init_ffmpeg;
|
||||
}
|
||||
|
||||
avformat_find_stream_info(_retu->video_format_ctx, NULL);
|
||||
|
@ -996,23 +1112,25 @@ av_session_t *av_init_session()
|
|||
if (_retu->webcam_decoder == NULL) {
|
||||
fprintf(stderr, "Unsupported codec!\n");
|
||||
//return -1;
|
||||
return NULL;
|
||||
goto failed_init_ffmpeg;
|
||||
}
|
||||
|
||||
if (_retu->webcam_decoder_ctx == NULL) {
|
||||
fprintf(stderr, "Init webcam_decoder_ctx failed!\n");
|
||||
//return -1;
|
||||
return NULL;
|
||||
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;
|
||||
return NULL;
|
||||
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 );
|
||||
|
@ -1023,18 +1141,18 @@ av_session_t *av_init_session()
|
|||
|
||||
/* ------------------ */
|
||||
|
||||
toxav_register_callstate_callback(callback_call_started, OnStart);
|
||||
toxav_register_callstate_callback(callback_call_canceled, OnCancel);
|
||||
toxav_register_callstate_callback(callback_call_rejected, OnReject);
|
||||
toxav_register_callstate_callback(callback_call_ended, OnEnd);
|
||||
toxav_register_callstate_callback(callback_recv_invite, OnInvite);
|
||||
toxav_register_callstate_callback(callback_call_started, av_OnStart);
|
||||
toxav_register_callstate_callback(callback_call_canceled, av_OnCancel);
|
||||
toxav_register_callstate_callback(callback_call_rejected, av_OnReject);
|
||||
toxav_register_callstate_callback(callback_call_ended, av_OnEnd);
|
||||
toxav_register_callstate_callback(callback_recv_invite, av_OnInvite);
|
||||
|
||||
toxav_register_callstate_callback(callback_recv_ringing, OnRinging);
|
||||
toxav_register_callstate_callback(callback_recv_starting, OnStarting);
|
||||
toxav_register_callstate_callback(callback_recv_ending, OnEnding);
|
||||
toxav_register_callstate_callback(callback_recv_ringing, av_OnRinging);
|
||||
toxav_register_callstate_callback(callback_recv_starting, av_OnStarting);
|
||||
toxav_register_callstate_callback(callback_recv_ending, av_OnEnding);
|
||||
|
||||
toxav_register_callstate_callback(callback_recv_error, OnError);
|
||||
toxav_register_callstate_callback(callback_requ_timeout, OnRequestTimeout);
|
||||
toxav_register_callstate_callback(callback_recv_error, av_OnError);
|
||||
toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout);
|
||||
|
||||
/* ------------------ */
|
||||
|
||||
|
@ -1310,6 +1428,8 @@ int main ( int argc, char *argv [] )
|
|||
|
||||
av_session_t *_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);
|
||||
|
||||
|
@ -1341,7 +1461,7 @@ int main ( int argc, char *argv [] )
|
|||
"================================================================================\n"
|
||||
"%s\n"
|
||||
"================================================================================"
|
||||
, _phone->_my_public_id );
|
||||
, trim_spaces(_phone->_my_public_id) );
|
||||
|
||||
|
||||
do_phone (_phone);
|
||||
|
|
42
toxav/rtp.c
Normal file → Executable file
42
toxav/rtp.c
Normal file → Executable file
|
@ -262,16 +262,7 @@ RTPHeader *extract_header ( const uint8_t *payload, int length )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ( _cc > 0 ) {
|
||||
_retu->csrc = calloc (_cc, sizeof (uint32_t));
|
||||
assert(_retu->csrc);
|
||||
|
||||
} else { /* But this should not happen ever */
|
||||
/* Deallocate */
|
||||
free(_retu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(_retu->csrc, 0, 16);
|
||||
|
||||
_retu->marker_payloadt = *_it;
|
||||
++_it;
|
||||
|
@ -362,14 +353,12 @@ uint8_t *add_header ( RTPHeader *header, uint8_t *payload )
|
|||
_it += 4;
|
||||
U32_to_bytes( _it, header->ssrc);
|
||||
|
||||
if ( header->csrc ) {
|
||||
uint8_t _x;
|
||||
|
||||
for ( _x = 0; _x < _cc; _x++ ) {
|
||||
_it += 4;
|
||||
U32_to_bytes( _it, header->csrc[_x]);
|
||||
}
|
||||
}
|
||||
|
||||
return _it + 4;
|
||||
}
|
||||
|
@ -424,18 +413,10 @@ RTPHeader *build_header ( RTPSession *session )
|
|||
_retu->timestamp = ((uint32_t)(current_time() / 1000)); /* micro to milli */
|
||||
_retu->ssrc = session->ssrc;
|
||||
|
||||
if ( session->cc > 0 ) {
|
||||
_retu->csrc = calloc(session->cc, sizeof (uint32_t));
|
||||
assert(_retu->csrc);
|
||||
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < session->cc; i++ ) {
|
||||
for ( i = 0; i < session->cc; i++ )
|
||||
_retu->csrc[i] = session->csrc[i];
|
||||
}
|
||||
} else {
|
||||
_retu->csrc = NULL;
|
||||
}
|
||||
|
||||
_retu->length = 12 /* Minimum header len */ + ( session->cc * size_32 );
|
||||
|
||||
|
@ -480,9 +461,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 */
|
||||
free (_retu->ext_header);
|
||||
free (_retu->header);
|
||||
free (_retu);
|
||||
rtp_free_msg(NULL, _retu);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
|
@ -545,7 +524,7 @@ 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 ) return -1; /* This packet is not encrypted properly */
|
||||
if ( _decrypted_length == -1 ) return -1; /* This packet is not encrypted properly */
|
||||
|
||||
/* Otherwise, if decryption is ok with new cycle, set new cycle
|
||||
*/
|
||||
|
@ -554,7 +533,7 @@ 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 ) return -1; /* This is just an error */
|
||||
if ( _decrypted_length == -1 ) return -1; /* This is just an error */
|
||||
|
||||
/* A new cycle setting. */
|
||||
memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES);
|
||||
|
@ -801,16 +780,11 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat
|
|||
void rtp_free_msg ( RTPSession *session, RTPMessage *msg )
|
||||
{
|
||||
if ( !session ) {
|
||||
free ( msg->header->csrc );
|
||||
|
||||
if ( msg->ext_header ) {
|
||||
free ( msg->ext_header->table );
|
||||
free ( msg->ext_header );
|
||||
}
|
||||
} else {
|
||||
if ( session->csrc != msg->header->csrc )
|
||||
free ( msg->header->csrc );
|
||||
|
||||
if ( msg->ext_header && session->ext_header != msg->ext_header ) {
|
||||
free ( msg->ext_header->table );
|
||||
free ( msg->ext_header );
|
||||
|
@ -920,12 +894,18 @@ int rtp_terminate_session ( RTPSession *session, Messenger *messenger )
|
|||
|
||||
custom_user_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL);
|
||||
|
||||
rtp_release_session_recv(session);
|
||||
|
||||
pthread_mutex_lock(&session->mutex);
|
||||
|
||||
free ( session->ext_header );
|
||||
free ( session->csrc );
|
||||
free ( session->decrypt_nonce );
|
||||
free ( session->encrypt_nonce );
|
||||
free ( session->nonce_cycle );
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
pthread_mutex_destroy(&session->mutex);
|
||||
|
||||
/* And finally free session */
|
||||
|
|
2
toxav/rtp.h
Normal file → Executable file
2
toxav/rtp.h
Normal file → Executable file
|
@ -47,7 +47,7 @@ typedef struct _RTPHeader {
|
|||
uint16_t sequnum; /* Sequence Number */
|
||||
uint32_t timestamp; /* Timestamp */
|
||||
uint32_t ssrc; /* SSRC */
|
||||
uint32_t *csrc; /* CSRC's table */
|
||||
uint32_t csrc[16]; /* CSRC's table */
|
||||
uint32_t length; /* Length of the header in payload string. */
|
||||
|
||||
} RTPHeader;
|
||||
|
|
113
toxav/toxav.c
Normal file → Executable file
113
toxav/toxav.c
Normal file → Executable file
|
@ -241,7 +241,7 @@ int toxav_cancel ( ToxAv *av, const char *reason )
|
|||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
return msi_cancel(av->msi_session, 0, (const uint8_t *)reason);
|
||||
return msi_cancel(av->msi_session, 0, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,7 +269,7 @@ int toxav_stop_call ( ToxAv *av )
|
|||
* @retval 0 Success.
|
||||
* @retval ToxAvError On error.
|
||||
*/
|
||||
int toxav_prepare_transmission ( ToxAv *av )
|
||||
int toxav_prepare_transmission ( ToxAv* av, int support_video )
|
||||
{
|
||||
assert(av->msi_session);
|
||||
|
||||
|
@ -293,6 +293,7 @@ int toxav_prepare_transmission ( ToxAv *av )
|
|||
return ErrorStartingAudioRtp;
|
||||
}
|
||||
|
||||
if ( support_video ) {
|
||||
av->rtp_sessions[video_index] = rtp_init_session (
|
||||
type_video,
|
||||
av->messenger,
|
||||
|
@ -308,7 +309,7 @@ int toxav_prepare_transmission ( ToxAv *av )
|
|||
fprintf(stderr, "Error while starting video RTP session!\n");
|
||||
return ErrorStartingVideoRtp;
|
||||
}
|
||||
|
||||
}
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
|
@ -322,21 +323,20 @@ int toxav_prepare_transmission ( ToxAv *av )
|
|||
*/
|
||||
int toxav_kill_transmission ( ToxAv *av )
|
||||
{
|
||||
/* Both sessions should be active at any time */
|
||||
if ( !av->rtp_sessions[0] || !av->rtp_sessions[0] )
|
||||
return ErrorNoTransmission;
|
||||
|
||||
|
||||
if ( -1 == rtp_terminate_session(av->rtp_sessions[audio_index], av->messenger) ) {
|
||||
if ( av->rtp_sessions[audio_index] && -1 == rtp_terminate_session(av->rtp_sessions[audio_index], av->messenger) ) {
|
||||
fprintf(stderr, "Error while terminating audio RTP session!\n");
|
||||
return ErrorTerminatingAudioRtp;
|
||||
}
|
||||
|
||||
if ( -1 == rtp_terminate_session(av->rtp_sessions[video_index], av->messenger) ) {
|
||||
if ( av->rtp_sessions[video_index] && -1 == rtp_terminate_session(av->rtp_sessions[video_index], av->messenger) ) {
|
||||
fprintf(stderr, "Error while terminating video RTP session!\n");
|
||||
return ErrorTerminatingVideoRtp;
|
||||
}
|
||||
|
||||
av->rtp_sessions[audio_index] = NULL;
|
||||
av->rtp_sessions[video_index] = NULL;
|
||||
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
|
@ -424,13 +424,14 @@ inline__ int toxav_recv_video ( ToxAv *av, vpx_image_t **output)
|
|||
|
||||
uint8_t packet [RTP_PAYLOAD_SIZE];
|
||||
int recved_size = 0;
|
||||
int error;
|
||||
|
||||
do {
|
||||
recved_size = toxav_recv_rtp_payload(av, TypeVideo, packet);
|
||||
|
||||
if (recved_size > 0) {
|
||||
printf("decode: %s\n", vpx_codec_err_to_string(vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0)));
|
||||
}
|
||||
if (recved_size > 0)
|
||||
fprintf(stderr, "Error decoding: %s\n", vpx_codec_err_to_string(vpx_codec_decode(&av->cs->v_decoder, packet, recved_size, NULL, 0)));
|
||||
|
||||
} while (recved_size > 0);
|
||||
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
|
@ -456,7 +457,7 @@ inline__ int toxav_recv_video ( ToxAv *av, vpx_image_t **output)
|
|||
inline__ int toxav_send_video ( ToxAv *av, 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) {
|
||||
printf("could not encode video frame\n");
|
||||
fprintf(stderr, "Could not encode video frame\n");
|
||||
return ErrorInternal;
|
||||
}
|
||||
|
||||
|
@ -500,7 +501,6 @@ inline__ int toxav_recv_audio ( ToxAv *av, int frame_size, int16_t *dest )
|
|||
int recved_size = toxav_recv_rtp_payload(av, TypeAudio, packet);
|
||||
|
||||
if ( recved_size == ErrorAudioPacketLost ) {
|
||||
printf("Lost packet\n");
|
||||
return opus_decode(av->cs->audio_decoder, NULL, 0, dest, frame_size, 1);
|
||||
} else if ( recved_size ) {
|
||||
return opus_decode(av->cs->audio_decoder, packet, recved_size, dest, frame_size, 0);
|
||||
|
@ -550,6 +550,24 @@ int toxav_get_peer_transmission_type ( ToxAv *av, int peer )
|
|||
return av->msi_session->call->type_peer[peer];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get id of peer participating in conversation
|
||||
*
|
||||
* @param av Handler
|
||||
* @param peer peer index
|
||||
* @return int
|
||||
* @retval ToxAvError No peer id
|
||||
*/
|
||||
int toxav_get_peer_id ( ToxAv* av, int peer )
|
||||
{
|
||||
assert(av->msi_session);
|
||||
|
||||
if ( peer < 0 || !av->msi_session->call || av->msi_session->call->peer_count <= peer )
|
||||
return ErrorInternal;
|
||||
|
||||
return av->msi_session->call->peers[peer];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get reference to an object that is handling av session.
|
||||
*
|
||||
|
@ -560,3 +578,68 @@ void *toxav_get_agent_handler ( ToxAv *av )
|
|||
{
|
||||
return av->agent_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Is video encoding supported
|
||||
*
|
||||
* @param av Handler
|
||||
* @return int
|
||||
* @retval 1 Yes.
|
||||
* @retval 0 No.
|
||||
*/
|
||||
inline__ int toxav_video_encoding ( ToxAv* av )
|
||||
{
|
||||
return av->cs->supported_actions & v_encoding;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Is video decoding supported
|
||||
*
|
||||
* @param av Handler
|
||||
* @return int
|
||||
* @retval 1 Yes.
|
||||
* @retval 0 No.
|
||||
*/
|
||||
inline__ int toxav_video_decoding ( ToxAv* av )
|
||||
{
|
||||
return av->cs->supported_actions & v_decoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Is audio encoding supported
|
||||
*
|
||||
* @param av Handler
|
||||
* @return int
|
||||
* @retval 1 Yes.
|
||||
* @retval 0 No.
|
||||
*/
|
||||
inline__ int toxav_audio_encoding ( ToxAv* av )
|
||||
{
|
||||
return av->cs->supported_actions & a_encoding;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Is audio decoding supported
|
||||
*
|
||||
* @param av Handler
|
||||
* @return int
|
||||
* @retval 1 Yes.
|
||||
* @retval 0 No.
|
||||
*/
|
||||
inline__ int toxav_audio_decoding ( ToxAv* av )
|
||||
{
|
||||
return av->cs->supported_actions & a_decoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get messenger handle
|
||||
*
|
||||
* @param av Handler.
|
||||
* @return Tox*
|
||||
*/
|
||||
inline__ Tox* toxav_get_tox ( ToxAv* av )
|
||||
{
|
||||
return (Tox*)av->messenger;
|
||||
}
|
86
toxav/toxav.h
Normal file → Executable file
86
toxav/toxav.h
Normal file → Executable file
|
@ -57,20 +57,20 @@ typedef struct Tox Tox;
|
|||
*/
|
||||
typedef enum {
|
||||
/* Requests */
|
||||
OnInvite,
|
||||
OnStart,
|
||||
OnCancel,
|
||||
OnReject,
|
||||
OnEnd,
|
||||
av_OnInvite,
|
||||
av_OnStart,
|
||||
av_OnCancel,
|
||||
av_OnReject,
|
||||
av_OnEnd,
|
||||
|
||||
/* Responses */
|
||||
OnRinging,
|
||||
OnStarting,
|
||||
OnEnding,
|
||||
av_OnRinging,
|
||||
av_OnStarting,
|
||||
av_OnEnding,
|
||||
|
||||
/* Protocol */
|
||||
OnError,
|
||||
OnRequestTimeout
|
||||
av_OnError,
|
||||
av_OnRequestTimeout
|
||||
|
||||
} ToxAvCallbackID;
|
||||
|
||||
|
@ -98,9 +98,8 @@ typedef enum {
|
|||
ErrorAudioPacketLost = -6, /* Indicating packet loss */
|
||||
ErrorStartingAudioRtp = -7, /* Error in toxav_prepare_transmission() */
|
||||
ErrorStartingVideoRtp = -8 , /* Error in toxav_prepare_transmission() */
|
||||
ErrorNoTransmission = -9, /* Returned in toxav_kill_transmission() */
|
||||
ErrorTerminatingAudioRtp = -10, /* Returned in toxav_kill_transmission() */
|
||||
ErrorTerminatingVideoRtp = -11, /* Returned in toxav_kill_transmission() */
|
||||
ErrorTerminatingAudioRtp = -9, /* Returned in toxav_kill_transmission() */
|
||||
ErrorTerminatingVideoRtp = -10, /* Returned in toxav_kill_transmission() */
|
||||
|
||||
} ToxAvError;
|
||||
|
||||
|
@ -205,11 +204,12 @@ int toxav_stop_call(ToxAv *av);
|
|||
* @brief Must be call before any RTP transmission occurs.
|
||||
*
|
||||
* @param av Handler.
|
||||
* @param support_video Is video supported ? 1 : 0
|
||||
* @return int
|
||||
* @retval 0 Success.
|
||||
* @retval ToxAvError On error.
|
||||
*/
|
||||
int toxav_prepare_transmission(ToxAv *av);
|
||||
int toxav_prepare_transmission(ToxAv *av, int support_video);
|
||||
|
||||
/**
|
||||
* @brief Call this at the end of the transmission.
|
||||
|
@ -281,6 +281,16 @@ int toxav_send_audio ( ToxAv *av, const int16_t *frame, int frame_size);
|
|||
*/
|
||||
int toxav_get_peer_transmission_type ( ToxAv *av, int peer );
|
||||
|
||||
/**
|
||||
* @brief Get id of peer participating in conversation
|
||||
*
|
||||
* @param av Handler
|
||||
* @param peer peer index
|
||||
* @return int
|
||||
* @retval ToxAvError No peer id
|
||||
*/
|
||||
int toxav_get_peer_id ( ToxAv* av, int peer );
|
||||
|
||||
/**
|
||||
* @brief Get reference to an object that is handling av session.
|
||||
*
|
||||
|
@ -289,4 +299,52 @@ int toxav_get_peer_transmission_type ( ToxAv *av, int peer );
|
|||
*/
|
||||
void *toxav_get_agent_handler ( ToxAv *av );
|
||||
|
||||
/**
|
||||
* @brief Is video encoding supported
|
||||
*
|
||||
* @param av Handler
|
||||
* @return int
|
||||
* @retval 1 Yes.
|
||||
* @retval 0 No.
|
||||
*/
|
||||
int toxav_video_encoding ( ToxAv* av );
|
||||
|
||||
/**
|
||||
* @brief Is video decoding supported
|
||||
*
|
||||
* @param av Handler
|
||||
* @return int
|
||||
* @retval 1 Yes.
|
||||
* @retval 0 No.
|
||||
*/
|
||||
int toxav_video_decoding ( ToxAv* av );
|
||||
|
||||
/**
|
||||
* @brief Is audio encoding supported
|
||||
*
|
||||
* @param av Handler
|
||||
* @return int
|
||||
* @retval 1 Yes.
|
||||
* @retval 0 No.
|
||||
*/
|
||||
int toxav_audio_encoding ( ToxAv* av );
|
||||
|
||||
/**
|
||||
* @brief Is audio decoding supported
|
||||
*
|
||||
* @param av Handler
|
||||
* @return int
|
||||
* @retval 1 Yes.
|
||||
* @retval 0 No.
|
||||
*/
|
||||
int toxav_audio_decoding ( ToxAv* av );
|
||||
|
||||
/**
|
||||
* @brief Get messenger handle
|
||||
*
|
||||
* @param av Handler.
|
||||
* @return Tox*
|
||||
*/
|
||||
Tox* toxav_get_tox ( ToxAv* av );
|
||||
|
||||
#endif /* __TOXAV */
|
Loading…
Reference in New Issue
Block a user