mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Started adding public API
This commit is contained in:
parent
b30b98aa0b
commit
292708c336
|
@ -37,9 +37,8 @@
|
||||||
#include <opus/opus.h>
|
#include <opus/opus.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "toxmsi.h"
|
#include "rtp.h"
|
||||||
#include "toxrtp.h"
|
#include "media.h"
|
||||||
#include "toxmedia.h"
|
|
||||||
|
|
||||||
struct jitter_buffer {
|
struct jitter_buffer {
|
||||||
RTPMessage **queue;
|
RTPMessage **queue;
|
||||||
|
@ -79,8 +78,6 @@ struct jitter_buffer *create_queue(int capacity)
|
||||||
/* returns 1 if 'a' has a higher sequence number than 'b' */
|
/* 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)
|
uint8_t sequence_number_older(uint16_t sn_a, uint16_t sn_b, uint32_t ts_a, uint32_t ts_b)
|
||||||
{
|
{
|
||||||
/* should be stable enough */
|
|
||||||
|
|
||||||
/* TODO: There is already this kind of function in toxrtp.c.
|
/* TODO: There is already this kind of function in toxrtp.c.
|
||||||
* Maybe merge?
|
* Maybe merge?
|
||||||
*/
|
*/
|
||||||
|
@ -141,7 +138,6 @@ int empty_queue(struct jitter_buffer *q)
|
||||||
{
|
{
|
||||||
while (q->size > 0) {
|
while (q->size > 0) {
|
||||||
q->size--;
|
q->size--;
|
||||||
/* FIXME: */
|
|
||||||
rtp_free_msg(NULL, q->queue[q->front]);
|
rtp_free_msg(NULL, q->queue[q->front]);
|
||||||
q->front++;
|
q->front++;
|
||||||
|
|
||||||
|
@ -207,64 +203,56 @@ int queue(struct jitter_buffer *q, RTPMessage *pk)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int init_receive_audio(codec_state *cs)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
cs->audio_decoder = opus_decoder_create(48000, 1, &rc );
|
|
||||||
|
|
||||||
if ( rc != OPUS_OK ){
|
int init_video_decoder(CodecState *cs)
|
||||||
printf("Error while starting audio decoder!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = opus_decoder_init(cs->audio_decoder, 48000, 1);
|
|
||||||
|
|
||||||
if ( rc != OPUS_OK ){
|
|
||||||
printf("Error while starting audio decoder!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
printf("Init audio decoder successful\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_receive_video(codec_state *cs)
|
|
||||||
{
|
{
|
||||||
cs->video_decoder = avcodec_find_decoder(VIDEO_CODEC);
|
cs->video_decoder = avcodec_find_decoder(VIDEO_CODEC);
|
||||||
|
|
||||||
if (!cs->video_decoder) {
|
if (!cs->video_decoder) {
|
||||||
printf("Init video_decoder failed\n");
|
fprintf(stderr, "Init video_decoder failed!\n");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cs->video_decoder_ctx = avcodec_alloc_context3(cs->video_decoder);
|
cs->video_decoder_ctx = avcodec_alloc_context3(cs->video_decoder);
|
||||||
|
|
||||||
if (!cs->video_decoder_ctx) {
|
if (!cs->video_decoder_ctx) {
|
||||||
printf("Init video_decoder_ctx failed\n");
|
fprintf(stderr, "Init video_decoder_ctx failed!\n");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avcodec_open2(cs->video_decoder_ctx, cs->video_decoder, NULL) < 0) {
|
if (avcodec_open2(cs->video_decoder_ctx, cs->video_decoder, NULL) < 0) {
|
||||||
printf("Opening video decoder failed\n");
|
fprintf(stderr, "Opening video decoder failed!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Init video decoder successful\n");
|
int init_audio_decoder(CodecState *cs, uint32_t audio_channels)
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_send_video(codec_state *cs)
|
|
||||||
{
|
{
|
||||||
cs->video_input_format = av_find_input_format(VIDEO_DRIVER);
|
int rc;
|
||||||
|
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");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (avformat_open_input(&cs->video_format_ctx, DEFAULT_WEBCAM, cs->video_input_format, NULL) != 0) {
|
|
||||||
printf("opening video_input_format failed\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int init_video_encoder(CodecState *cs, const char* webcam, const char* video_driver, uint32_t video_bitrate)
|
||||||
|
{
|
||||||
|
cs->video_input_format = av_find_input_format(video_driver);
|
||||||
|
|
||||||
|
if (avformat_open_input(&cs->video_format_ctx, webcam, cs->video_input_format, NULL) != 0) {
|
||||||
|
fprintf(stderr, "Opening video_input_format failed!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
avformat_find_stream_info(cs->video_format_ctx, NULL);
|
avformat_find_stream_info(cs->video_format_ctx, NULL);
|
||||||
av_dump_format(cs->video_format_ctx, 0, DEFAULT_WEBCAM, 0);
|
av_dump_format(cs->video_format_ctx, 0, webcam, 0);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -279,42 +267,42 @@ int init_send_video(codec_state *cs)
|
||||||
cs->webcam_decoder = avcodec_find_decoder(cs->webcam_decoder_ctx->codec_id);
|
cs->webcam_decoder = avcodec_find_decoder(cs->webcam_decoder_ctx->codec_id);
|
||||||
|
|
||||||
if (cs->webcam_decoder == NULL) {
|
if (cs->webcam_decoder == NULL) {
|
||||||
printf("Unsupported codec\n");
|
fprintf(stderr, "Unsupported codec!\n");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cs->webcam_decoder_ctx == NULL) {
|
if (cs->webcam_decoder_ctx == NULL) {
|
||||||
printf("init webcam_decoder_ctx failed\n");
|
fprintf(stderr, "Init webcam_decoder_ctx failed!\n");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avcodec_open2(cs->webcam_decoder_ctx, cs->webcam_decoder, NULL) < 0) {
|
if (avcodec_open2(cs->webcam_decoder_ctx, cs->webcam_decoder, NULL) < 0) {
|
||||||
printf("opening webcam decoder failed\n");
|
fprintf(stderr, "Opening webcam decoder failed!\n");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC);
|
cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC);
|
||||||
|
|
||||||
if (!cs->video_encoder) {
|
if (!cs->video_encoder) {
|
||||||
printf("init video_encoder failed\n");
|
fprintf(stderr, "Init video_encoder failed!\n");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder);
|
cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder);
|
||||||
|
|
||||||
if (!cs->video_encoder_ctx) {
|
if (!cs->video_encoder_ctx) {
|
||||||
printf("init video_encoder_ctx failed\n");
|
fprintf(stderr, "Init video_encoder_ctx failed!\n");
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cs->video_encoder_ctx->bit_rate = VIDEO_BITRATE;
|
cs->video_encoder_ctx->bit_rate = video_bitrate;
|
||||||
cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate;
|
cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate;
|
||||||
av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0);
|
av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0);
|
||||||
av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0);
|
av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0);
|
||||||
|
|
||||||
cs->video_encoder_ctx->thread_count = 4;
|
cs->video_encoder_ctx->thread_count = 4;
|
||||||
cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95;
|
cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95;
|
||||||
cs->video_encoder_ctx->rc_buffer_size = VIDEO_BITRATE * 6;
|
cs->video_encoder_ctx->rc_buffer_size = video_bitrate * 6;
|
||||||
cs->video_encoder_ctx->profile = 3;
|
cs->video_encoder_ctx->profile = 3;
|
||||||
cs->video_encoder_ctx->qmax = 54;
|
cs->video_encoder_ctx->qmax = 54;
|
||||||
cs->video_encoder_ctx->qmin = 4;
|
cs->video_encoder_ctx->qmin = 4;
|
||||||
|
@ -326,66 +314,84 @@ int init_send_video(codec_state *cs)
|
||||||
cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height;
|
cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height;
|
||||||
|
|
||||||
if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) {
|
if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) {
|
||||||
printf("opening video encoder failed\n");
|
fprintf(stderr, "Opening video encoder failed!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("init video encoder successful\n");
|
int init_audio_encoder(CodecState *cs)
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_send_audio(codec_state *cs)
|
|
||||||
{
|
{
|
||||||
cs->support_send_audio = 0;
|
|
||||||
|
|
||||||
int err = OPUS_OK;
|
int err = OPUS_OK;
|
||||||
cs->audio_bitrate = AUDIO_BITRATE;
|
cs->audio_encoder = opus_encoder_create(cs->audio_sample_rate, 1, OPUS_APPLICATION_VOIP, &err);
|
||||||
cs->audio_encoder = opus_encoder_create(AUDIO_SAMPLE_RATE, 1, OPUS_APPLICATION_VOIP, &err);
|
|
||||||
err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate));
|
err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_BITRATE(cs->audio_bitrate));
|
||||||
err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
|
err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_COMPLEXITY(10));
|
||||||
err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
|
err = opus_encoder_ctl(cs->audio_encoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
|
||||||
|
|
||||||
|
/* NOTE: What do we do with this? */
|
||||||
int nfo;
|
int nfo;
|
||||||
err = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_LOOKAHEAD(&nfo));
|
err = opus_encoder_ctl(cs->audio_encoder, OPUS_GET_LOOKAHEAD(&nfo));
|
||||||
/* printf("Encoder lookahead delay : %d\n", nfo); */
|
|
||||||
printf("init audio encoder successful\n");
|
|
||||||
|
|
||||||
return 1;
|
return err == OPUS_OK ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int init_encoder(codec_state *cs)
|
|
||||||
|
CodecState* codec_init_session ( uint32_t audio_bitrate,
|
||||||
|
uint16_t audio_frame_duration,
|
||||||
|
uint32_t audio_sample_rate,
|
||||||
|
uint32_t audio_channels,
|
||||||
|
uint32_t video_bitrate,
|
||||||
|
const char* webcam,
|
||||||
|
const char* webcam_driver )
|
||||||
{
|
{
|
||||||
|
CodecState* _retu = av_calloc(sizeof(CodecState), 1);
|
||||||
|
assert(_retu);
|
||||||
|
|
||||||
|
|
||||||
avdevice_register_all();
|
avdevice_register_all();
|
||||||
avcodec_register_all();
|
avcodec_register_all();
|
||||||
avdevice_register_all();
|
|
||||||
av_register_all();
|
av_register_all();
|
||||||
|
|
||||||
pthread_mutex_init(&cs->ctrl_mutex, NULL);
|
|
||||||
|
|
||||||
cs->support_send_video = init_send_video(cs);
|
_retu->audio_bitrate = audio_bitrate;
|
||||||
cs->support_send_audio = init_send_audio(cs);
|
_retu->audio_sample_rate = audio_sample_rate;
|
||||||
|
|
||||||
cs->send_audio = 1;
|
pthread_mutex_init(&_retu->ctrl_mutex, NULL);
|
||||||
cs->send_video = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
|
/* Encoders */
|
||||||
|
if ( 0 == init_video_encoder(_retu, webcam, webcam_driver, video_bitrate) )
|
||||||
|
printf("Video encoder initialized!\n");
|
||||||
|
|
||||||
|
if ( 0 == init_audio_encoder(_retu) )
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int init_decoder(codec_state *cs)
|
void codec_terminate_session ( CodecState* cs )
|
||||||
{
|
{
|
||||||
avdevice_register_all();
|
if ( cs->audio_encoder ) {
|
||||||
avcodec_register_all();
|
opus_encoder_destroy(cs->audio_encoder);
|
||||||
avdevice_register_all();
|
printf("Terminated encoder!\n");
|
||||||
av_register_all();
|
}
|
||||||
|
|
||||||
cs->receive_video = 0;
|
if ( cs->audio_decoder ) {
|
||||||
cs->receive_audio = 0;
|
opus_decoder_destroy(cs->audio_decoder);
|
||||||
|
printf("Terminated decoder!\n");
|
||||||
cs->support_receive_video = init_receive_video(cs);
|
}
|
||||||
cs->support_receive_audio = init_receive_audio(cs);
|
|
||||||
|
/* TODO: Terminate video */
|
||||||
cs->receive_audio = 1;
|
|
||||||
cs->receive_video = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
|
@ -27,8 +27,6 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "toxrtp.h"
|
|
||||||
#include "toxmsi.h"
|
|
||||||
#include "../toxcore/tox.h"
|
#include "../toxcore/tox.h"
|
||||||
|
|
||||||
/* Video encoding/decoding */
|
/* Video encoding/decoding */
|
||||||
|
@ -75,16 +73,7 @@
|
||||||
#define DEFAULT_WEBCAM "0"
|
#define DEFAULT_WEBCAM "0"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct _CodecState{
|
||||||
uint8_t send_audio;
|
|
||||||
uint8_t receive_audio;
|
|
||||||
uint8_t send_video;
|
|
||||||
uint8_t receive_video;
|
|
||||||
|
|
||||||
uint8_t support_send_audio;
|
|
||||||
uint8_t support_send_video;
|
|
||||||
uint8_t support_receive_audio;
|
|
||||||
uint8_t support_receive_video;
|
|
||||||
|
|
||||||
/* video encoding */
|
/* video encoding */
|
||||||
AVInputFormat *video_input_format;
|
AVInputFormat *video_input_format;
|
||||||
|
@ -102,19 +91,19 @@ typedef struct {
|
||||||
/* audio encoding */
|
/* audio encoding */
|
||||||
OpusEncoder *audio_encoder;
|
OpusEncoder *audio_encoder;
|
||||||
int audio_bitrate;
|
int audio_bitrate;
|
||||||
|
int audio_sample_rate;
|
||||||
|
|
||||||
/* audio decoding */
|
/* audio decoding */
|
||||||
OpusDecoder *audio_decoder;
|
OpusDecoder *audio_decoder;
|
||||||
|
|
||||||
uint8_t req_video_refresh;
|
|
||||||
|
|
||||||
pthread_mutex_t ctrl_mutex;
|
pthread_mutex_t ctrl_mutex;
|
||||||
|
|
||||||
|
|
||||||
uint32_t frame_rate;
|
uint32_t frame_rate;
|
||||||
|
|
||||||
} codec_state;
|
} CodecState;
|
||||||
|
|
||||||
|
typedef struct _RTPMessage RTPMessage;
|
||||||
|
|
||||||
struct jitter_buffer *create_queue(int capacity);
|
struct jitter_buffer *create_queue(int capacity);
|
||||||
int empty_queue(struct jitter_buffer *q);
|
int empty_queue(struct jitter_buffer *q);
|
||||||
|
@ -123,8 +112,14 @@ int queue(struct jitter_buffer *q, RTPMessage *pk);
|
||||||
RTPMessage *dequeue(struct jitter_buffer *q, int *success);
|
RTPMessage *dequeue(struct jitter_buffer *q, int *success);
|
||||||
|
|
||||||
|
|
||||||
int init_encoder(codec_state *cs);
|
CodecState* codec_init_session( uint32_t audio_bitrate,
|
||||||
int init_decoder(codec_state *cs);
|
uint16_t audio_frame_duration,
|
||||||
|
uint32_t audio_sample_rate,
|
||||||
|
uint32_t audio_channels,
|
||||||
|
uint32_t video_bitrate,
|
||||||
|
const char* webcam,
|
||||||
|
const char* webcam_driver );
|
||||||
|
|
||||||
|
void codec_terminate_session(CodecState* cs);
|
||||||
|
|
||||||
#endif
|
#endif
|
44
toxav/toxmsi.c → toxav/msi.c
Executable file → Normal file
44
toxav/toxmsi.c → toxav/msi.c
Executable file → Normal file
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#define _BSD_SOURCE
|
#define _BSD_SOURCE
|
||||||
|
|
||||||
#include "toxmsi.h"
|
#include "msi.h"
|
||||||
#include "../toxcore/util.h"
|
#include "../toxcore/util.h"
|
||||||
#include "../toxcore/network.h"
|
#include "../toxcore/network.h"
|
||||||
#include "../toxcore/event.h"
|
#include "../toxcore/event.h"
|
||||||
|
@ -335,8 +335,6 @@ MSIMessage* msi_new_message ( uint8_t type, const uint8_t* type_id ) {
|
||||||
MSIMessage* _retu = calloc ( sizeof ( MSIMessage ), 1 );
|
MSIMessage* _retu = calloc ( sizeof ( MSIMessage ), 1 );
|
||||||
assert ( _retu );
|
assert ( _retu );
|
||||||
|
|
||||||
memset ( _retu, 0, sizeof ( MSIMessage ) );
|
|
||||||
|
|
||||||
if ( type == TYPE_REQUEST ) {
|
if ( type == TYPE_REQUEST ) {
|
||||||
ALLOCATE_HEADER ( _retu->request, type_id, strlen ( (const char*)type_id ) )
|
ALLOCATE_HEADER ( _retu->request, type_id, strlen ( (const char*)type_id ) )
|
||||||
|
|
||||||
|
@ -641,7 +639,7 @@ int handle_error ( MSISession* session, MSICallError errid, uint32_t to ) {
|
||||||
session->last_error_id = errid;
|
session->last_error_id = errid;
|
||||||
session->last_error_str = stringify_error ( errid );
|
session->last_error_str = stringify_error ( errid );
|
||||||
|
|
||||||
event.rise ( callbacks[MSI_OnError], session );
|
event.rise ( callbacks[MSI_OnError], session->agent_handler );
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -692,12 +690,12 @@ void* handle_timeout ( void* arg )
|
||||||
/* Cancel all? */
|
/* Cancel all? */
|
||||||
uint16_t _it = 0;
|
uint16_t _it = 0;
|
||||||
for ( ; _it < _peer_count; _it++ )
|
for ( ; _it < _peer_count; _it++ )
|
||||||
msi_cancel ( arg, _peers[_it] );
|
msi_cancel ( arg, _peers[_it], (const uint8_t*)"Timeout" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
( *callbacks[MSI_OnTimeout] ) ( arg );
|
( *callbacks[MSI_OnTimeout] ) ( _session->agent_handler );
|
||||||
( *callbacks[MSI_OnEnding ] ) ( arg );
|
( *callbacks[MSI_OnEnding ] ) ( _session->agent_handler );
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -829,7 +827,7 @@ int handle_recv_invite ( MSISession* session, MSIMessage* msg ) {
|
||||||
send_message ( session, _msg_ringing, msg->friend_id );
|
send_message ( session, _msg_ringing, msg->friend_id );
|
||||||
free_message ( _msg_ringing );
|
free_message ( _msg_ringing );
|
||||||
|
|
||||||
event.rise ( callbacks[MSI_OnInvite], session );
|
event.rise ( callbacks[MSI_OnInvite], session->agent_handler );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -852,7 +850,7 @@ int handle_recv_start ( MSISession* session, MSIMessage* msg ) {
|
||||||
|
|
||||||
flush_peer_type ( session, msg, 0 );
|
flush_peer_type ( session, msg, 0 );
|
||||||
|
|
||||||
event.rise ( callbacks[MSI_OnStart], session );
|
event.rise ( callbacks[MSI_OnStart], session->agent_handler );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -868,7 +866,7 @@ int handle_recv_reject ( MSISession* session, MSIMessage* msg ) {
|
||||||
free_message ( _msg_end );
|
free_message ( _msg_end );
|
||||||
|
|
||||||
event.timer_release ( session->call->request_timer_id );
|
event.timer_release ( session->call->request_timer_id );
|
||||||
event.rise ( callbacks[MSI_OnReject], session );
|
event.rise ( callbacks[MSI_OnReject], session->agent_handler );
|
||||||
session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout );
|
session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -882,7 +880,7 @@ int handle_recv_cancel ( MSISession* session, MSIMessage* msg ) {
|
||||||
|
|
||||||
terminate_call ( session );
|
terminate_call ( session );
|
||||||
|
|
||||||
event.rise ( callbacks[MSI_OnCancel], session );
|
event.rise ( callbacks[MSI_OnCancel], session->agent_handler );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -899,7 +897,7 @@ int handle_recv_end ( MSISession* session, MSIMessage* msg ) {
|
||||||
|
|
||||||
terminate_call ( session );
|
terminate_call ( session );
|
||||||
|
|
||||||
event.rise ( callbacks[MSI_OnEnd], session );
|
event.rise ( callbacks[MSI_OnEnd], session->agent_handler );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -912,7 +910,7 @@ int handle_recv_ringing ( MSISession* session, MSIMessage* msg ) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
session->call->ringing_timer_id = event.timer_alloc ( handle_timeout, session, session->call->ringing_tout_ms );
|
session->call->ringing_timer_id = event.timer_alloc ( handle_timeout, session, session->call->ringing_tout_ms );
|
||||||
event.rise ( callbacks[MSI_OnRinging], session );
|
event.rise ( callbacks[MSI_OnRinging], session->agent_handler );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -950,7 +948,7 @@ int handle_recv_starting ( MSISession* session, MSIMessage* msg ) {
|
||||||
|
|
||||||
flush_peer_type ( session, msg, 0 );
|
flush_peer_type ( session, msg, 0 );
|
||||||
|
|
||||||
event.rise ( callbacks[MSI_OnStarting], session );
|
event.rise ( callbacks[MSI_OnStarting], session->agent_handler );
|
||||||
event.timer_release ( session->call->ringing_timer_id );
|
event.timer_release ( session->call->ringing_timer_id );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -964,7 +962,7 @@ int handle_recv_ending ( MSISession* session, MSIMessage* msg ) {
|
||||||
|
|
||||||
terminate_call ( session );
|
terminate_call ( session );
|
||||||
|
|
||||||
event.rise ( callbacks[MSI_OnEnding], session );
|
event.rise ( callbacks[MSI_OnEnding], session->agent_handler );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -980,7 +978,7 @@ int handle_recv_error ( MSISession* session, MSIMessage* msg ) {
|
||||||
|
|
||||||
terminate_call ( session );
|
terminate_call ( session );
|
||||||
|
|
||||||
event.rise ( callbacks[MSI_OnEnding], session );
|
event.rise ( callbacks[MSI_OnEnding], session->agent_handler );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1138,14 +1136,13 @@ void msi_register_callback ( MSICallback callback, MSICallbackID id )
|
||||||
* @return MSISession* The created session.
|
* @return MSISession* The created session.
|
||||||
* @retval NULL Error occured.
|
* @retval NULL Error occured.
|
||||||
*/
|
*/
|
||||||
MSISession* msi_init_session ( Tox* messenger, const uint8_t* user_agent ) {
|
MSISession* msi_init_session ( Tox* messenger, const uint8_t* ua_name ) {
|
||||||
assert ( messenger );
|
assert ( messenger );
|
||||||
assert ( user_agent );
|
|
||||||
|
|
||||||
MSISession* _retu = calloc ( sizeof ( MSISession ), 1 );
|
MSISession* _retu = calloc ( sizeof ( MSISession ), 1 );
|
||||||
assert ( _retu );
|
assert ( _retu );
|
||||||
|
|
||||||
_retu->user_agent = user_agent;
|
_retu->ua_name = ua_name;
|
||||||
_retu->messenger_handle = messenger;
|
_retu->messenger_handle = messenger;
|
||||||
_retu->agent_handler = NULL;
|
_retu->agent_handler = NULL;
|
||||||
|
|
||||||
|
@ -1300,14 +1297,17 @@ int msi_answer ( MSISession* session, MSICallType call_type ) {
|
||||||
* @brief Cancel request.
|
* @brief Cancel request.
|
||||||
*
|
*
|
||||||
* @param session Control session.
|
* @param session Control session.
|
||||||
* @param friend_id The friend.
|
* @param reason Set optional reason header. Pass NULL if none.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
int msi_cancel ( MSISession* session, int friend_id ) {
|
int msi_cancel ( MSISession* session, uint32_t peer, const uint8_t* reason ) {
|
||||||
assert ( session );
|
assert ( session );
|
||||||
|
|
||||||
MSIMessage* _msg_cancel = msi_new_message ( TYPE_REQUEST, stringify_request ( cancel ) );
|
MSIMessage* _msg_cancel = msi_new_message ( TYPE_REQUEST, stringify_request ( cancel ) );
|
||||||
send_message ( session, _msg_cancel, friend_id );
|
|
||||||
|
if ( reason ) msi_msg_set_reason(_msg_cancel, reason, strlen((const char*)reason));
|
||||||
|
|
||||||
|
send_message ( session, _msg_cancel, peer );
|
||||||
free_message ( _msg_cancel );
|
free_message ( _msg_cancel );
|
||||||
|
|
||||||
terminate_call ( session );
|
terminate_call ( session );
|
9
toxav/toxmsi.h → toxav/msi.h
Executable file → Normal file
9
toxav/toxmsi.h → toxav/msi.h
Executable file → Normal file
|
@ -103,7 +103,7 @@ typedef struct _MSISession {
|
||||||
int last_error_id; /* Determine the last error */
|
int last_error_id; /* Determine the last error */
|
||||||
const uint8_t* last_error_str;
|
const uint8_t* last_error_str;
|
||||||
|
|
||||||
const uint8_t* user_agent;
|
const uint8_t* ua_name;
|
||||||
|
|
||||||
void* agent_handler; /* Pointer to an object that is handling msi */
|
void* agent_handler; /* Pointer to an object that is handling msi */
|
||||||
Tox* messenger_handle;
|
Tox* messenger_handle;
|
||||||
|
@ -156,7 +156,7 @@ void msi_register_callback(MSICallback callback, MSICallbackID id);
|
||||||
* @return MSISession* The created session.
|
* @return MSISession* The created session.
|
||||||
* @retval NULL Error occured.
|
* @retval NULL Error occured.
|
||||||
*/
|
*/
|
||||||
MSISession* msi_init_session ( Tox* messenger, const uint8_t* user_agent );
|
MSISession* msi_init_session ( Tox* messenger, const uint8_t* ua_name );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -205,10 +205,11 @@ int msi_answer ( MSISession* session, MSICallType call_type );
|
||||||
* @brief Cancel request.
|
* @brief Cancel request.
|
||||||
*
|
*
|
||||||
* @param session Control session.
|
* @param session Control session.
|
||||||
* @param friend_id The friend.
|
* @param peer To which peer.
|
||||||
|
* @param reason Set optional reason header. Pass NULL if none.
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
int msi_cancel ( MSISession* session, int friend_id );
|
int msi_cancel ( MSISession* session, uint32_t peer, const uint8_t* reason );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
401
toxav/phone.c
401
toxav/phone.c
|
@ -51,9 +51,8 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <opus/opus.h>
|
#include <opus/opus.h>
|
||||||
|
|
||||||
#include "toxmsi.h"
|
#include "media.h"
|
||||||
#include "toxrtp.h"
|
#include "toxav.h"
|
||||||
#include "toxmedia.h"
|
|
||||||
#include "../toxcore/event.h"
|
#include "../toxcore/event.h"
|
||||||
#include "../toxcore/tox.h"
|
#include "../toxcore/tox.h"
|
||||||
|
|
||||||
|
@ -75,13 +74,9 @@ typedef struct av_friend_s {
|
||||||
} av_friend_t;
|
} av_friend_t;
|
||||||
|
|
||||||
typedef struct av_session_s {
|
typedef struct av_session_s {
|
||||||
MSISession* _msi;
|
|
||||||
RTPSession* _rtp_audio;
|
|
||||||
RTPSession* _rtp_video;
|
|
||||||
|
|
||||||
/* Encoding/decoding/capturing/playing */
|
/* Encoding/decoding/capturing/playing */
|
||||||
|
ToxAv* av;
|
||||||
|
|
||||||
codec_state* cs;
|
|
||||||
VideoPicture video_picture;
|
VideoPicture video_picture;
|
||||||
struct ALCdevice *audio_capture_device;
|
struct ALCdevice *audio_capture_device;
|
||||||
|
|
||||||
|
@ -91,8 +86,9 @@ typedef struct av_session_s {
|
||||||
/* context for converting webcam image format to something the video encoder can use */
|
/* context for converting webcam image format to something the video encoder can use */
|
||||||
struct SwsContext *sws_ctx;
|
struct SwsContext *sws_ctx;
|
||||||
|
|
||||||
/**/
|
/* Thread running control */
|
||||||
|
int running_decaud, running_encaud,
|
||||||
|
running_decvid, running_encvid;
|
||||||
|
|
||||||
pthread_mutex_t _mutex;
|
pthread_mutex_t _mutex;
|
||||||
|
|
||||||
|
@ -243,7 +239,7 @@ static void fraddr_to_str(uint8_t *id_bin, char *id_str)
|
||||||
|
|
||||||
int display_received_frame(av_session_t* _phone, AVFrame *r_video_frame)
|
int display_received_frame(av_session_t* _phone, AVFrame *r_video_frame)
|
||||||
{
|
{
|
||||||
codec_state* cs = _phone->cs;
|
CodecState* cs = get_cs_temp(_phone->av);
|
||||||
AVPicture pict;
|
AVPicture pict;
|
||||||
SDL_LockYUVOverlay(_phone->video_picture.bmp);
|
SDL_LockYUVOverlay(_phone->video_picture.bmp);
|
||||||
|
|
||||||
|
@ -268,71 +264,15 @@ int display_received_frame(av_session_t* _phone, AVFrame *r_video_frame)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int video_encoder_refresh(codec_state *cs, int bps)
|
|
||||||
{
|
|
||||||
if (cs->video_encoder_ctx)
|
|
||||||
avcodec_close(cs->video_encoder_ctx);
|
|
||||||
|
|
||||||
cs->video_encoder = avcodec_find_encoder(VIDEO_CODEC);
|
|
||||||
|
|
||||||
if (!cs->video_encoder) {
|
|
||||||
printf("init video_encoder failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cs->video_encoder_ctx = avcodec_alloc_context3(cs->video_encoder);
|
|
||||||
|
|
||||||
if (!cs->video_encoder_ctx) {
|
|
||||||
printf("init video_encoder_ctx failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cs->video_encoder_ctx->bit_rate = bps;
|
|
||||||
cs->video_encoder_ctx->rc_min_rate = cs->video_encoder_ctx->rc_max_rate = cs->video_encoder_ctx->bit_rate;
|
|
||||||
av_opt_set_double(cs->video_encoder_ctx->priv_data, "max-intra-rate", 90, 0);
|
|
||||||
av_opt_set(cs->video_encoder_ctx->priv_data, "quality", "realtime", 0);
|
|
||||||
|
|
||||||
cs->video_encoder_ctx->thread_count = 4;
|
|
||||||
cs->video_encoder_ctx->rc_buffer_aggressivity = 0.95;
|
|
||||||
cs->video_encoder_ctx->rc_buffer_size = bps * 6;
|
|
||||||
cs->video_encoder_ctx->profile = 0;
|
|
||||||
cs->video_encoder_ctx->qmax = 54;
|
|
||||||
cs->video_encoder_ctx->qmin = 4;
|
|
||||||
AVRational myrational = {1, 25};
|
|
||||||
cs->video_encoder_ctx->time_base = myrational;
|
|
||||||
cs->video_encoder_ctx->gop_size = 99999;
|
|
||||||
cs->video_encoder_ctx->pix_fmt = PIX_FMT_YUV420P;
|
|
||||||
cs->video_encoder_ctx->width = cs->webcam_decoder_ctx->width;
|
|
||||||
cs->video_encoder_ctx->height = cs->webcam_decoder_ctx->height;
|
|
||||||
|
|
||||||
if (avcodec_open2(cs->video_encoder_ctx, cs->video_encoder, NULL) < 0) {
|
|
||||||
printf("opening video encoder failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int video_decoder_refresh(av_session_t* _phone, int width, int height)
|
|
||||||
{
|
|
||||||
printf("need to refresh\n");
|
|
||||||
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, _phone->cs->video_decoder_ctx->pix_fmt, width, height, PIX_FMT_YUV420P,
|
|
||||||
SWS_BILINEAR, NULL, NULL, NULL);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *encode_video_thread(void *arg)
|
void *encode_video_thread(void *arg)
|
||||||
{
|
{
|
||||||
INFO("Started encode video thread!");
|
INFO("Started encode video thread!");
|
||||||
|
|
||||||
av_session_t* _phone = arg;
|
av_session_t* _phone = arg;
|
||||||
|
|
||||||
codec_state *cs = _phone->cs;
|
_phone->running_encvid = 1;
|
||||||
|
|
||||||
|
CodecState *cs = get_cs_temp(_phone->av);
|
||||||
AVPacket pkt1, *packet = &pkt1;
|
AVPacket pkt1, *packet = &pkt1;
|
||||||
int p = 0;
|
int p = 0;
|
||||||
int got_packet;
|
int got_packet;
|
||||||
|
@ -354,7 +294,7 @@ void *encode_video_thread(void *arg)
|
||||||
cs->webcam_decoder_ctx->pix_fmt, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height, PIX_FMT_YUV420P,
|
cs->webcam_decoder_ctx->pix_fmt, cs->webcam_decoder_ctx->width, cs->webcam_decoder_ctx->height, PIX_FMT_YUV420P,
|
||||||
SWS_BILINEAR, NULL, NULL, NULL);
|
SWS_BILINEAR, NULL, NULL, NULL);
|
||||||
|
|
||||||
while (cs->send_video) {
|
while (_phone->running_encvid) {
|
||||||
|
|
||||||
if (av_read_frame(cs->video_format_ctx, packet) < 0) {
|
if (av_read_frame(cs->video_format_ctx, packet) < 0) {
|
||||||
printf("error reading frame\n");
|
printf("error reading frame\n");
|
||||||
|
@ -400,9 +340,7 @@ void *encode_video_thread(void *arg)
|
||||||
|
|
||||||
if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n");
|
if (!enc_video_packet.data) fprintf(stderr, "video packet data is NULL\n");
|
||||||
|
|
||||||
if ( 0 > rtp_send_msg ( _phone->_rtp_video, _phone->_messenger, enc_video_packet.data, enc_video_packet.size) ) {
|
toxav_send_rtp_payload(_phone->av, TypeVideo, enc_video_packet.data, enc_video_packet.size);
|
||||||
printf("Failed sending message\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
av_free_packet(&enc_video_packet);
|
av_free_packet(&enc_video_packet);
|
||||||
}
|
}
|
||||||
|
@ -420,6 +358,9 @@ void *encode_video_thread(void *arg)
|
||||||
avcodec_close(cs->webcam_decoder_ctx);
|
avcodec_close(cs->webcam_decoder_ctx);
|
||||||
avcodec_close(cs->video_encoder_ctx);
|
avcodec_close(cs->video_encoder_ctx);
|
||||||
pthread_mutex_unlock(&cs->ctrl_mutex);
|
pthread_mutex_unlock(&cs->ctrl_mutex);
|
||||||
|
|
||||||
|
_phone->running_encvid = -1;
|
||||||
|
|
||||||
pthread_exit ( NULL );
|
pthread_exit ( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,8 +368,8 @@ void *encode_audio_thread(void *arg)
|
||||||
{
|
{
|
||||||
INFO("Started encode audio thread!");
|
INFO("Started encode audio thread!");
|
||||||
av_session_t* _phone = arg;
|
av_session_t* _phone = arg;
|
||||||
|
_phone->running_encaud = 1;
|
||||||
|
|
||||||
codec_state *cs = _phone->cs;
|
|
||||||
unsigned char encoded_data[4096];
|
unsigned char encoded_data[4096];
|
||||||
int encoded_size = 0;
|
int encoded_size = 0;
|
||||||
int16_t frame[4096];
|
int16_t frame[4096];
|
||||||
|
@ -436,28 +377,31 @@ void *encode_audio_thread(void *arg)
|
||||||
ALint sample = 0;
|
ALint sample = 0;
|
||||||
alcCaptureStart((ALCdevice*)_phone->audio_capture_device);
|
alcCaptureStart((ALCdevice*)_phone->audio_capture_device);
|
||||||
|
|
||||||
while (cs->send_audio) {
|
while (_phone->running_encaud) {
|
||||||
alcGetIntegerv((ALCdevice*)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
|
alcGetIntegerv((ALCdevice*)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
|
||||||
|
|
||||||
if (sample >= frame_size) {
|
if (sample >= frame_size) {
|
||||||
alcCaptureSamples((ALCdevice*)_phone->audio_capture_device, frame, frame_size);
|
alcCaptureSamples((ALCdevice*)_phone->audio_capture_device, frame, frame_size);
|
||||||
encoded_size = opus_encode(cs->audio_encoder, frame, frame_size, encoded_data, MAX_RTP_SIZE);
|
|
||||||
|
encoded_size = toxav_encode_audio(_phone->av, frame, frame_size, encoded_data);
|
||||||
|
|
||||||
if (encoded_size <= 0) {
|
if (encoded_size <= 0) {
|
||||||
printf("Could not encode audio packet\n");
|
printf("Could not encode audio packet\n");
|
||||||
} else {
|
} else {
|
||||||
rtp_send_msg ( _phone->_rtp_audio, _phone->_messenger, encoded_data, encoded_size );
|
if ( -1 == toxav_send_rtp_payload(_phone->av, TypeAudio, encoded_data, encoded_size) )
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up codecs */
|
/* clean up codecs *
|
||||||
pthread_mutex_lock(&cs->ctrl_mutex);
|
pthread_mutex_lock(&cs->ctrl_mutex);*/
|
||||||
alcCaptureStop((ALCdevice*)_phone->audio_capture_device);
|
alcCaptureStop((ALCdevice*)_phone->audio_capture_device);
|
||||||
alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device);
|
alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device);
|
||||||
pthread_mutex_unlock(&cs->ctrl_mutex);
|
/*pthread_mutex_unlock(&cs->ctrl_mutex);*/
|
||||||
|
_phone->running_encaud = -1;
|
||||||
pthread_exit ( NULL );
|
pthread_exit ( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,10 +409,14 @@ void *decode_video_thread(void *arg)
|
||||||
{
|
{
|
||||||
INFO("Started decode video thread!");
|
INFO("Started decode video thread!");
|
||||||
av_session_t* _phone = arg;
|
av_session_t* _phone = arg;
|
||||||
|
_phone->running_decvid = 1;
|
||||||
|
|
||||||
codec_state *cs = _phone->cs;
|
CodecState *cs = get_cs_temp(_phone->av);
|
||||||
cs->video_stream = 0;
|
cs->video_stream = 0;
|
||||||
RTPMessage *r_msg;
|
|
||||||
|
int recved_size;
|
||||||
|
uint8_t dest[RTP_PAYLOAD_SIZE];
|
||||||
|
|
||||||
int dec_frame_finished;
|
int dec_frame_finished;
|
||||||
AVFrame *r_video_frame;
|
AVFrame *r_video_frame;
|
||||||
r_video_frame = avcodec_alloc_frame();
|
r_video_frame = avcodec_alloc_frame();
|
||||||
|
@ -477,20 +425,34 @@ void *decode_video_thread(void *arg)
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
|
|
||||||
while (cs->receive_video) {
|
while (_phone->running_decvid) {
|
||||||
r_msg = rtp_recv_msg ( _phone->_rtp_video );
|
|
||||||
|
recved_size = toxav_recv_rtp_payload(_phone->av, TypeVideo, 1, dest);
|
||||||
|
|
||||||
|
if (recved_size) {
|
||||||
|
memcpy(dec_video_packet.data, dest, recved_size);
|
||||||
|
dec_video_packet.size = recved_size;
|
||||||
|
|
||||||
if (r_msg) {
|
|
||||||
memcpy(dec_video_packet.data, r_msg->data, r_msg->length);
|
|
||||||
dec_video_packet.size = r_msg->length;
|
|
||||||
avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet);
|
avcodec_decode_video2(cs->video_decoder_ctx, r_video_frame, &dec_frame_finished, &dec_video_packet);
|
||||||
|
|
||||||
if (dec_frame_finished) {
|
if (dec_frame_finished) {
|
||||||
|
|
||||||
|
/* Check if size has changed */
|
||||||
if (cs->video_decoder_ctx->width != width || cs->video_decoder_ctx->height != height) {
|
if (cs->video_decoder_ctx->width != width || cs->video_decoder_ctx->height != height) {
|
||||||
|
|
||||||
width = cs->video_decoder_ctx->width;
|
width = cs->video_decoder_ctx->width;
|
||||||
height = cs->video_decoder_ctx->height;
|
height = cs->video_decoder_ctx->height;
|
||||||
|
|
||||||
printf("w: %d h: %d \n", width, height);
|
printf("w: %d h: %d \n", width, height);
|
||||||
video_decoder_refresh(_phone, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
display_received_frame(_phone, r_video_frame);
|
display_received_frame(_phone, r_video_frame);
|
||||||
|
@ -498,18 +460,20 @@ void *decode_video_thread(void *arg)
|
||||||
/* TODO: request the sender to create a new i-frame immediatly */
|
/* TODO: request the sender to create a new i-frame immediatly */
|
||||||
printf("Bad video packet\n");
|
printf("Bad video packet\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
rtp_free_msg(NULL, r_msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up codecs */
|
/* clean up codecs */
|
||||||
pthread_mutex_lock(&cs->ctrl_mutex);
|
|
||||||
av_free(r_video_frame);
|
av_free(r_video_frame);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&cs->ctrl_mutex);
|
||||||
avcodec_close(cs->video_decoder_ctx);
|
avcodec_close(cs->video_decoder_ctx);
|
||||||
pthread_mutex_unlock(&cs->ctrl_mutex);
|
pthread_mutex_unlock(&cs->ctrl_mutex);
|
||||||
|
|
||||||
|
_phone->running_decvid = -1;
|
||||||
|
|
||||||
pthread_exit ( NULL );
|
pthread_exit ( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,9 +481,10 @@ void *decode_audio_thread(void *arg)
|
||||||
{
|
{
|
||||||
INFO("Started decode audio thread!");
|
INFO("Started decode audio thread!");
|
||||||
av_session_t* _phone = arg;
|
av_session_t* _phone = arg;
|
||||||
|
_phone->running_decaud = 1;
|
||||||
|
|
||||||
codec_state *cs = _phone->cs;
|
int recved_size;
|
||||||
RTPMessage *r_msg;
|
uint8_t dest [RTP_PAYLOAD_SIZE];
|
||||||
|
|
||||||
int frame_size = AUDIO_FRAME_SIZE;
|
int frame_size = AUDIO_FRAME_SIZE;
|
||||||
int data_size;
|
int data_size;
|
||||||
|
@ -538,7 +503,7 @@ void *decode_audio_thread(void *arg)
|
||||||
alSourcei(source, AL_LOOPING, AL_FALSE);
|
alSourcei(source, AL_LOOPING, AL_FALSE);
|
||||||
|
|
||||||
ALuint buffer;
|
ALuint buffer;
|
||||||
ALint val;
|
ALint ready;
|
||||||
|
|
||||||
uint16_t zeros[frame_size];
|
uint16_t zeros[frame_size];
|
||||||
memset(zeros, 0, frame_size);
|
memset(zeros, 0, frame_size);
|
||||||
|
@ -557,49 +522,28 @@ void *decode_audio_thread(void *arg)
|
||||||
goto ending;
|
goto ending;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct jitter_buffer *j_buf = NULL;
|
|
||||||
|
|
||||||
j_buf = create_queue(20);
|
|
||||||
|
|
||||||
int success = 0;
|
|
||||||
|
|
||||||
int dec_frame_len = 0;
|
int dec_frame_len = 0;
|
||||||
|
|
||||||
|
while (_phone->running_decaud) {
|
||||||
|
|
||||||
while (cs->receive_audio) {
|
alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready);
|
||||||
|
|
||||||
r_msg = rtp_recv_msg ( _phone->_rtp_audio );
|
recved_size = toxav_recv_rtp_payload(_phone->av, TypeAudio, ready, dest);
|
||||||
|
|
||||||
if (r_msg) {
|
if ( recved_size == ErrorAudioPacketLost ) {
|
||||||
/* push the packet into the queue */
|
|
||||||
queue(j_buf, r_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
success = 0;
|
|
||||||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
|
|
||||||
|
|
||||||
/* grab a packet from the queue */
|
|
||||||
if (val > 0) {
|
|
||||||
r_msg = dequeue(j_buf, &success);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success > 0) {
|
|
||||||
/* good packet */
|
|
||||||
if (success == 1) {
|
|
||||||
dec_frame_len = opus_decode(cs->audio_decoder, r_msg->data, r_msg->length, PCM, frame_size, 0);
|
|
||||||
rtp_free_msg(NULL, r_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* lost packet */
|
|
||||||
else if (success == 2) {
|
|
||||||
printf("Lost packet\n");
|
printf("Lost packet\n");
|
||||||
dec_frame_len = opus_decode(cs->audio_decoder, NULL, 0, PCM, frame_size, 1);
|
dec_frame_len = toxav_decode_audio(_phone->av, NULL, 0, frame_size, PCM);
|
||||||
|
|
||||||
|
} else if ( recved_size ) {
|
||||||
|
dec_frame_len = toxav_decode_audio(_phone->av, dest, recved_size, frame_size, PCM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec_frame_len) {
|
|
||||||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
|
|
||||||
|
|
||||||
if (val <= 0)
|
/* Play the packet */
|
||||||
|
if (dec_frame_len) {
|
||||||
|
alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready);
|
||||||
|
|
||||||
|
if (ready <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
alSourceUnqueueBuffers(source, 1, &buffer);
|
alSourceUnqueueBuffers(source, 1, &buffer);
|
||||||
|
@ -619,13 +563,9 @@ void *decode_audio_thread(void *arg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
alGetSourcei(source, AL_SOURCE_STATE, &val);
|
alGetSourcei(source, AL_SOURCE_STATE, &ready);
|
||||||
|
|
||||||
if (val != AL_PLAYING)
|
if (ready != AL_PLAYING) alSourcePlay(source);
|
||||||
alSourcePlay(source);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
|
@ -642,7 +582,10 @@ ending:
|
||||||
alcDestroyContext(ctx);
|
alcDestroyContext(ctx);
|
||||||
alcCloseDevice(dev);
|
alcCloseDevice(dev);
|
||||||
|
|
||||||
pthread_mutex_unlock(&cs->ctrl_mutex);
|
pthread_mutex_unlock(&cs->ctrl_mutex); */
|
||||||
|
|
||||||
|
_phone->running_decaud = -1;
|
||||||
|
|
||||||
pthread_exit ( NULL );
|
pthread_exit ( NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,61 +593,42 @@ ending:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int phone_startmedia_loop ( av_session_t* _phone )
|
int phone_startmedia_loop ( ToxAv* arg )
|
||||||
{
|
{
|
||||||
if ( !_phone ){
|
if ( !arg ){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_phone->_rtp_audio = rtp_init_session (
|
toxav_prepare_transmission(arg);
|
||||||
type_audio,
|
|
||||||
_phone->_messenger,
|
|
||||||
_phone->_msi->call->peers[0],
|
|
||||||
_phone->_msi->call->key_peer,
|
|
||||||
_phone->_msi->call->key_local,
|
|
||||||
_phone->_msi->call->nonce_peer,
|
|
||||||
_phone->_msi->call->nonce_local
|
|
||||||
);
|
|
||||||
|
|
||||||
_phone->_rtp_video = rtp_init_session (
|
|
||||||
type_video,
|
|
||||||
_phone->_messenger,
|
|
||||||
_phone->_msi->call->peers[0],
|
|
||||||
_phone->_msi->call->key_peer,
|
|
||||||
_phone->_msi->call->key_local,
|
|
||||||
_phone->_msi->call->nonce_peer,
|
|
||||||
_phone->_msi->call->nonce_local
|
|
||||||
);
|
|
||||||
|
|
||||||
init_encoder(_phone->cs);
|
|
||||||
init_decoder(_phone->cs);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rise all threads
|
* Rise all threads
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Only checks for last peer */
|
/* Only checks for last peer */
|
||||||
if ( _phone->_msi->call->type_peer[0] == type_video && 0 > event.rise(encode_video_thread, _phone) )
|
if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo &&
|
||||||
|
0 > event.rise(encode_video_thread, toxav_get_agent_handler(arg)) )
|
||||||
{
|
{
|
||||||
INFO("Error while starting encode_video_thread()");
|
INFO("Error while starting encode_video_thread()");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Always send audio */
|
/* Always send audio */
|
||||||
if ( 0 > event.rise(encode_audio_thread, _phone) )
|
if ( 0 > event.rise(encode_audio_thread, toxav_get_agent_handler(arg)) )
|
||||||
{
|
{
|
||||||
INFO("Error while starting encode_audio_thread()");
|
INFO("Error while starting encode_audio_thread()");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only checks for last peer */
|
/* Only checks for last peer */
|
||||||
if ( _phone->_msi->call->type_peer[0] == type_video && 0 > event.rise(decode_video_thread, _phone) )
|
if ( toxav_get_peer_transmission_type(arg, 0) == TypeVideo &&
|
||||||
|
0 > event.rise(decode_video_thread, toxav_get_agent_handler(arg)) )
|
||||||
{
|
{
|
||||||
INFO("Error while starting decode_video_thread()");
|
INFO("Error while starting decode_video_thread()");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( 0 > event.rise(decode_audio_thread, _phone) )
|
if ( 0 > event.rise(decode_audio_thread, toxav_get_agent_handler(arg)) )
|
||||||
{
|
{
|
||||||
INFO("Error while starting decode_audio_thread()");
|
INFO("Error while starting decode_audio_thread()");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -734,13 +658,13 @@ int phone_startmedia_loop ( av_session_t* _phone )
|
||||||
|
|
||||||
void* callback_recv_invite ( void* _arg )
|
void* callback_recv_invite ( void* _arg )
|
||||||
{
|
{
|
||||||
MSISession* _msi = _arg;
|
assert(_arg);
|
||||||
|
|
||||||
switch ( _msi->call->type_peer[_msi->call->peer_count - 1] ){
|
switch ( toxav_get_peer_transmission_type(_arg, 0) ){
|
||||||
case type_audio:
|
case TypeAudio:
|
||||||
INFO( "Incoming audio call!");
|
INFO( "Incoming audio call!");
|
||||||
break;
|
break;
|
||||||
case type_video:
|
case TypeVideo:
|
||||||
INFO( "Incoming video call!");
|
INFO( "Incoming video call!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -754,8 +678,7 @@ void* callback_recv_ringing ( void* _arg )
|
||||||
}
|
}
|
||||||
void* callback_recv_starting ( void* _arg )
|
void* callback_recv_starting ( void* _arg )
|
||||||
{
|
{
|
||||||
MSISession* _session = _arg;
|
if ( 0 != phone_startmedia_loop(_arg) ){
|
||||||
if ( 0 != phone_startmedia_loop(_session->agent_handler) ){
|
|
||||||
INFO("Starting call failed!");
|
INFO("Starting call failed!");
|
||||||
} else {
|
} else {
|
||||||
INFO ("Call started! ( press h to hangup )");
|
INFO ("Call started! ( press h to hangup )");
|
||||||
|
@ -764,14 +687,20 @@ void* callback_recv_starting ( void* _arg )
|
||||||
}
|
}
|
||||||
void* callback_recv_ending ( void* _arg )
|
void* callback_recv_ending ( void* _arg )
|
||||||
{
|
{
|
||||||
av_session_t* _phone = ((MSISession*)_arg)->agent_handler;
|
av_session_t* _phone = toxav_get_agent_handler(_arg);
|
||||||
|
|
||||||
_phone->cs->send_audio = 0;
|
_phone->running_encaud = 0;
|
||||||
_phone->cs->send_video = 0;
|
_phone->running_decaud = 0;
|
||||||
_phone->cs->receive_audio = 0;
|
_phone->running_encvid = 0;
|
||||||
_phone->cs->receive_video = 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(10000000);
|
||||||
|
|
||||||
INFO ( "Call ended!" );
|
INFO ( "Call ended!" );
|
||||||
|
@ -780,16 +709,15 @@ void* callback_recv_ending ( void* _arg )
|
||||||
|
|
||||||
void* callback_recv_error ( void* _arg )
|
void* callback_recv_error ( void* _arg )
|
||||||
{
|
{
|
||||||
MSISession* _session = _arg;
|
/*MSISession* _session = _arg;
|
||||||
|
|
||||||
INFO( "Error: %s", _session->last_error_str );
|
INFO( "Error: %s", _session->last_error_str ); */
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* callback_call_started ( void* _arg )
|
void* callback_call_started ( void* _arg )
|
||||||
{
|
{
|
||||||
MSISession* _session = _arg;
|
if ( 0 != phone_startmedia_loop(_arg) ){
|
||||||
if ( 0 != phone_startmedia_loop(_session->agent_handler) ){
|
|
||||||
INFO("Starting call failed!");
|
INFO("Starting call failed!");
|
||||||
} else {
|
} else {
|
||||||
INFO ("Call started! ( press h to hangup )");
|
INFO ("Call started! ( press h to hangup )");
|
||||||
|
@ -809,16 +737,23 @@ void* callback_call_rejected ( void* _arg )
|
||||||
}
|
}
|
||||||
void* callback_call_ended ( void* _arg )
|
void* callback_call_ended ( void* _arg )
|
||||||
{
|
{
|
||||||
av_session_t* _phone = ((MSISession*)_arg)->agent_handler;
|
av_session_t* _phone = toxav_get_agent_handler(_arg);
|
||||||
|
|
||||||
_phone->cs->send_audio = 0;
|
_phone->running_encaud = 0;
|
||||||
_phone->cs->send_video = 0;
|
_phone->running_decaud = 0;
|
||||||
_phone->cs->receive_audio = 0;
|
_phone->running_encvid = 0;
|
||||||
_phone->cs->receive_video = 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(10000000);
|
||||||
|
|
||||||
|
toxav_kill_transmission(_phone->av);
|
||||||
INFO ( "Call ended!" );
|
INFO ( "Call ended!" );
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
@ -844,9 +779,7 @@ av_session_t* av_init_session()
|
||||||
}
|
}
|
||||||
|
|
||||||
_retu->_friends = NULL;
|
_retu->_friends = NULL;
|
||||||
|
_retu->av = toxav_new(_retu->_messenger, _retu, _USERAGENT);
|
||||||
_retu->_rtp_audio = NULL;
|
|
||||||
_retu->_rtp_video = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
const ALchar *_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
const ALchar *_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||||
|
@ -879,8 +812,6 @@ av_session_t* av_init_session()
|
||||||
INFO("Selected: %d ( %s )", selection, device_names[selection]);
|
INFO("Selected: %d ( %s )", selection, device_names[selection]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_retu->cs = av_calloc(sizeof(codec_state), 1);
|
|
||||||
|
|
||||||
_retu->audio_capture_device =
|
_retu->audio_capture_device =
|
||||||
(struct ALCdevice*)alcCaptureOpenDevice(
|
(struct ALCdevice*)alcCaptureOpenDevice(
|
||||||
device_names[selection], AUDIO_SAMPLE_RATE, AL_FORMAT_MONO16, AUDIO_FRAME_SIZE * 4);
|
device_names[selection], AUDIO_SAMPLE_RATE, AL_FORMAT_MONO16, AUDIO_FRAME_SIZE * 4);
|
||||||
|
@ -897,29 +828,22 @@ av_session_t* av_init_session()
|
||||||
fraddr_to_str( _byte_address, _retu->_my_public_id );
|
fraddr_to_str( _byte_address, _retu->_my_public_id );
|
||||||
|
|
||||||
|
|
||||||
/* Initialize msi */
|
|
||||||
_retu->_msi = msi_init_session ( _retu->_messenger, (const uint8_t*)_USERAGENT );
|
|
||||||
|
|
||||||
if ( !_retu->_msi ) {
|
|
||||||
fprintf ( stderr, "msi_init_session() failed\n" );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_retu->_msi->agent_handler = _retu;
|
|
||||||
|
|
||||||
/* ------------------ */
|
/* ------------------ */
|
||||||
msi_register_callback(callback_call_started, MSI_OnStart);
|
|
||||||
msi_register_callback(callback_call_canceled, MSI_OnCancel);
|
|
||||||
msi_register_callback(callback_call_rejected, MSI_OnReject);
|
|
||||||
msi_register_callback(callback_call_ended, MSI_OnEnd);
|
|
||||||
msi_register_callback(callback_recv_invite, MSI_OnInvite);
|
|
||||||
|
|
||||||
msi_register_callback(callback_recv_ringing, MSI_OnRinging);
|
toxav_register_callstate_callback(callback_call_started, OnStart);
|
||||||
msi_register_callback(callback_recv_starting, MSI_OnStarting);
|
toxav_register_callstate_callback(callback_call_canceled, OnCancel);
|
||||||
msi_register_callback(callback_recv_ending, MSI_OnEnding);
|
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_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_error, OnError);
|
||||||
|
toxav_register_callstate_callback(callback_requ_timeout, OnTimeout);
|
||||||
|
|
||||||
msi_register_callback(callback_recv_error, MSI_OnError);
|
|
||||||
msi_register_callback(callback_requ_timeout, MSI_OnTimeout);
|
|
||||||
/* ------------------ */
|
/* ------------------ */
|
||||||
|
|
||||||
return _retu;
|
return _retu;
|
||||||
|
@ -927,17 +851,18 @@ av_session_t* av_init_session()
|
||||||
|
|
||||||
int av_terminate_session(av_session_t* _phone)
|
int av_terminate_session(av_session_t* _phone)
|
||||||
{
|
{
|
||||||
if ( _phone->_msi->call ){
|
toxav_hangup(_phone->av);
|
||||||
msi_hangup(_phone->_msi); /* Hangup the phone first */
|
|
||||||
}
|
|
||||||
|
|
||||||
free(_phone->_friends);
|
free(_phone->_friends);
|
||||||
msi_terminate_session(_phone->_msi);
|
|
||||||
pthread_mutex_destroy ( &_phone->_mutex );
|
pthread_mutex_destroy ( &_phone->_mutex );
|
||||||
|
|
||||||
Tox* _p = _phone->_messenger;
|
Tox* _p = _phone->_messenger;
|
||||||
_phone->_messenger = NULL; usleep(100000); /* Wait for tox_pool to end */
|
_phone->_messenger = NULL; usleep(100000); /* Wait for tox_poll to end */
|
||||||
|
|
||||||
tox_kill(_p);
|
tox_kill(_p);
|
||||||
|
toxav_kill(_phone->av);
|
||||||
|
|
||||||
|
free(_phone);
|
||||||
|
|
||||||
printf("\r[i] Quit!\n");
|
printf("\r[i] Quit!\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1047,22 +972,17 @@ void do_phone ( av_session_t* _phone )
|
||||||
} break;
|
} break;
|
||||||
case 'c':
|
case 'c':
|
||||||
{
|
{
|
||||||
if ( _phone->_msi->call ){
|
ToxAvCallType _ctype;
|
||||||
INFO("Already in a call");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
MSICallType _ctype;
|
|
||||||
|
|
||||||
if ( _len < 5 ){
|
if ( _len < 5 ){
|
||||||
INFO("Invalid input; usage: c a/v [friend]");
|
INFO("Invalid input; usage: c a/v [friend]");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if ( _line[2] == 'a' || _line[2] != 'v' ){ /* default and audio */
|
else if ( _line[2] == 'a' || _line[2] != 'v' ){ /* default and audio */
|
||||||
_ctype = type_audio;
|
_ctype = TypeAudio;
|
||||||
}
|
}
|
||||||
else { /* video */
|
else { /* video */
|
||||||
_ctype = type_video;
|
_ctype = TypeVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* _end;
|
char* _end;
|
||||||
|
@ -1073,45 +993,41 @@ void do_phone ( av_session_t* _phone )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set timeout */
|
if ( toxav_call(_phone->av, _friend, _ctype, 30) == ErrorAlreadyInCall ){
|
||||||
msi_invite ( _phone->_msi, _ctype, 10 * 1000, _friend );
|
INFO("Already in a call");
|
||||||
INFO("Calling friend: %d!", _friend);
|
break;
|
||||||
|
}
|
||||||
|
else INFO("Calling friend: %d!", _friend);
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case 'h':
|
case 'h':
|
||||||
{
|
{
|
||||||
if ( !_phone->_msi->call ){
|
if ( toxav_hangup(_phone->av) == ErrorNoCall ) {
|
||||||
INFO("No call!");
|
INFO("No call!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else INFO("Hung up...");
|
||||||
msi_hangup(_phone->_msi);
|
|
||||||
|
|
||||||
INFO("Hung up...");
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case 'a':
|
case 'a':
|
||||||
{
|
{
|
||||||
|
ToxAvError rc;
|
||||||
if ( _phone->_msi->call && _phone->_msi->call->state != call_starting ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( _len > 1 && _line[2] == 'v' )
|
if ( _len > 1 && _line[2] == 'v' )
|
||||||
msi_answer(_phone->_msi, type_video);
|
rc = toxav_answer(_phone->av, TypeVideo);
|
||||||
else
|
else
|
||||||
msi_answer(_phone->_msi, type_audio);
|
rc = toxav_answer(_phone->av, TypeAudio);
|
||||||
|
|
||||||
|
if ( rc == ErrorInvalidState ) {
|
||||||
|
INFO("No call to answer!");
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case 'r':
|
case 'r':
|
||||||
{
|
{
|
||||||
if ( _phone->_msi->call && _phone->_msi->call->state != call_starting ){
|
if ( toxav_reject(_phone->av, "User action") == ErrorInvalidState )
|
||||||
break;
|
INFO("No state to cancel!");
|
||||||
}
|
else INFO("Call Rejected...");
|
||||||
|
|
||||||
msi_reject(_phone->_msi, NULL);
|
|
||||||
|
|
||||||
INFO("Call Rejected...");
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
case 'q':
|
case 'q':
|
||||||
|
@ -1124,7 +1040,6 @@ void do_phone ( av_session_t* _phone )
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
INFO("Invalid command!");
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
3
toxav/toxrtp.c → toxav/rtp.c
Executable file → Normal file
3
toxav/toxrtp.c → toxav/rtp.c
Executable file → Normal file
|
@ -26,7 +26,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include "toxrtp.h"
|
#include "rtp.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -245,6 +245,7 @@ RTPHeader* extract_header ( const uint8_t* payload, int length )
|
||||||
* Now it my happen that this is out of order but
|
* Now it my happen that this is out of order but
|
||||||
* it cuts down chances of parsing some invalid value
|
* it cuts down chances of parsing some invalid value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( GET_FLAG_VERSION(_retu) != RTP_VERSION ){
|
if ( GET_FLAG_VERSION(_retu) != RTP_VERSION ){
|
||||||
/* Deallocate */
|
/* Deallocate */
|
||||||
free(_retu);
|
free(_retu);
|
0
toxav/toxrtp.h → toxav/rtp.h
Executable file → Normal file
0
toxav/toxrtp.h → toxav/rtp.h
Executable file → Normal file
352
toxav/toxav.c
Normal file
352
toxav/toxav.c
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
/** toxav.c
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Report bugs/suggestions at either #tox-dev @ freenode.net:6667 or
|
||||||
|
* my email: eniz_vukovic@hotmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include "toxav.h"
|
||||||
|
#include "../toxcore/tox.h"
|
||||||
|
#include "rtp.h"
|
||||||
|
#include "msi.h"
|
||||||
|
#include "media.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define inline__ inline __attribute__((always_inline))
|
||||||
|
|
||||||
|
static const uint8_t audio_index = 0, video_index = 1;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ts_closing,
|
||||||
|
ts_running,
|
||||||
|
ts_closed
|
||||||
|
|
||||||
|
} ThreadState;
|
||||||
|
|
||||||
|
typedef struct _ToxAv
|
||||||
|
{
|
||||||
|
Tox* messenger;
|
||||||
|
|
||||||
|
MSISession* msi_session; /** Main msi session */
|
||||||
|
|
||||||
|
RTPSession* rtp_sessions[2]; /* Audio is first and video is second */
|
||||||
|
|
||||||
|
/* TODO: Add media session */
|
||||||
|
struct jitter_buffer* j_buf;
|
||||||
|
CodecState* cs;
|
||||||
|
/* TODO: Add media session threads */
|
||||||
|
|
||||||
|
|
||||||
|
void* agent_handler;
|
||||||
|
} ToxAv;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************************************************
|
||||||
|
********************************************************************************************************************
|
||||||
|
********************************************************************************************************************
|
||||||
|
********************************************************************************************************************
|
||||||
|
********************************************************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* PUBLIC API FUNCTIONS IMPLEMENTATIONS
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
********************************************************************************************************************
|
||||||
|
********************************************************************************************************************
|
||||||
|
********************************************************************************************************************
|
||||||
|
********************************************************************************************************************
|
||||||
|
********************************************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ToxAv* toxav_new( Tox* messenger, void* useragent, const char* ua_name )
|
||||||
|
{
|
||||||
|
ToxAv* av = calloc ( sizeof(ToxAv), 1);
|
||||||
|
|
||||||
|
av->msi_session = msi_init_session(messenger, (const unsigned char*) ua_name );
|
||||||
|
av->msi_session->agent_handler = av;
|
||||||
|
|
||||||
|
av->rtp_sessions[0] = av->rtp_sessions [1] = NULL;
|
||||||
|
|
||||||
|
av->messenger = messenger;
|
||||||
|
|
||||||
|
/* NOTE: This should be user defined or? */
|
||||||
|
av->j_buf = create_queue(20);
|
||||||
|
|
||||||
|
av->cs = codec_init_session(AUDIO_BITRATE, AUDIO_FRAME_DURATION, AUDIO_SAMPLE_RATE, 1, VIDEO_BITRATE, DEFAULT_WEBCAM, VIDEO_DRIVER);
|
||||||
|
|
||||||
|
av->agent_handler = useragent;
|
||||||
|
|
||||||
|
return av;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toxav_kill ( ToxAv* av )
|
||||||
|
{
|
||||||
|
msi_terminate_session(av->msi_session);
|
||||||
|
|
||||||
|
if ( av->rtp_sessions[audio_index] ) {
|
||||||
|
rtp_terminate_session(av->rtp_sessions[audio_index], av->msi_session->messenger_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( av->rtp_sessions[video_index] ) {
|
||||||
|
rtp_terminate_session(av->rtp_sessions[video_index], av->msi_session->messenger_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
codec_terminate_session(av->cs);
|
||||||
|
|
||||||
|
free(av);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toxav_register_callstate_callback ( ToxAVCallback callback, ToxAvCallbackID id )
|
||||||
|
{
|
||||||
|
msi_register_callback((MSICallback)callback, (MSICallbackID) id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int toxav_call (ToxAv* av, int user, ToxAvCallType call_type, int ringing_seconds )
|
||||||
|
{
|
||||||
|
if ( av->msi_session->call ) {
|
||||||
|
return ErrorAlreadyInCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msi_invite(av->msi_session, call_type, ringing_seconds * 1000, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
int toxav_hangup ( ToxAv* av )
|
||||||
|
{
|
||||||
|
if ( !av->msi_session->call ) {
|
||||||
|
return ErrorNoCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( av->msi_session->call->state != call_active ) {
|
||||||
|
return ErrorInvalidState;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msi_hangup(av->msi_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
int toxav_answer ( ToxAv* av, ToxAvCallType call_type )
|
||||||
|
{
|
||||||
|
if ( !av->msi_session->call ) {
|
||||||
|
return ErrorNoCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( av->msi_session->call->state != call_starting ) {
|
||||||
|
return ErrorInvalidState;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msi_answer(av->msi_session, call_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int toxav_reject ( ToxAv* av, const char* reason )
|
||||||
|
{
|
||||||
|
if ( !av->msi_session->call ) {
|
||||||
|
return ErrorNoCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( av->msi_session->call->state != call_starting ) {
|
||||||
|
return ErrorInvalidState;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msi_reject(av->msi_session, (const uint8_t*) reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
int toxav_cancel ( ToxAv* av, const char* reason )
|
||||||
|
{
|
||||||
|
if ( !av->msi_session->call ) {
|
||||||
|
return ErrorNoCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msi_cancel(av->msi_session, 0, (const uint8_t*)reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* You can stop the call at any state */
|
||||||
|
int toxav_stop_call ( ToxAv* av )
|
||||||
|
{
|
||||||
|
if ( !av->msi_session->call ) {
|
||||||
|
return ErrorNoCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
return msi_stopcall(av->msi_session);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int toxav_prepare_transmission ( ToxAv* av )
|
||||||
|
{
|
||||||
|
assert(av->msi_session);
|
||||||
|
if ( !av->msi_session || !av->msi_session->call ) {
|
||||||
|
return ErrorNoCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
av->rtp_sessions[audio_index] = rtp_init_session(
|
||||||
|
type_audio,
|
||||||
|
av->messenger,
|
||||||
|
av->msi_session->call->peers[0],
|
||||||
|
av->msi_session->call->key_peer,
|
||||||
|
av->msi_session->call->key_local,
|
||||||
|
av->msi_session->call->nonce_peer,
|
||||||
|
av->msi_session->call->nonce_local
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if ( !av->rtp_sessions[audio_index] ) {
|
||||||
|
fprintf(stderr, "Error while starting audio RTP session!\n");
|
||||||
|
return ErrorStartingAudioRtp;
|
||||||
|
}
|
||||||
|
|
||||||
|
av->rtp_sessions[video_index] = rtp_init_session (
|
||||||
|
type_video,
|
||||||
|
av->messenger,
|
||||||
|
av->msi_session->call->peers[0],
|
||||||
|
av->msi_session->call->key_peer,
|
||||||
|
av->msi_session->call->key_local,
|
||||||
|
av->msi_session->call->nonce_peer,
|
||||||
|
av->msi_session->call->nonce_local
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if ( !av->rtp_sessions[video_index] ) {
|
||||||
|
fprintf(stderr, "Error while starting video RTP session!\n");
|
||||||
|
return ErrorStartingVideoRtp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) ) {
|
||||||
|
fprintf(stderr, "Error while terminating audio RTP session!\n");
|
||||||
|
return ErrorTerminatingAudioRtp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( -1 == rtp_terminate_session(av->rtp_sessions[video_index], av->messenger) ) {
|
||||||
|
fprintf(stderr, "Error while terminating video RTP session!\n");
|
||||||
|
return ErrorTerminatingVideoRtp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ErrorNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline__ int toxav_send_rtp_payload ( ToxAv* av, ToxAvCallType type, const uint8_t* payload, uint16_t length )
|
||||||
|
{
|
||||||
|
if ( av->rtp_sessions[type - TypeAudio] )
|
||||||
|
return rtp_send_msg ( av->rtp_sessions[type - TypeAudio], av->msi_session->messenger_handle, payload, length );
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline__ int toxav_recv_rtp_payload ( ToxAv* av, ToxAvCallType type, int ready, uint8_t* dest )
|
||||||
|
{
|
||||||
|
if ( !dest ) return ErrorInternal;
|
||||||
|
|
||||||
|
if ( !av->rtp_sessions[type - TypeAudio] ) return ErrorNoRtpSession;
|
||||||
|
|
||||||
|
RTPMessage* message;
|
||||||
|
|
||||||
|
if ( type == TypeAudio ) {
|
||||||
|
|
||||||
|
message = rtp_recv_msg(av->rtp_sessions[audio_index]);
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
/* push the packet into the queue */
|
||||||
|
queue(av->j_buf, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ready) {
|
||||||
|
int success = 0;
|
||||||
|
message = dequeue(av->j_buf, &success);
|
||||||
|
|
||||||
|
if ( success == 2) return ErrorAudioPacketLost;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message = rtp_recv_msg(av->rtp_sessions[video_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( message ) {
|
||||||
|
memcpy(dest, message->data, message->length);
|
||||||
|
|
||||||
|
int length = message->length;
|
||||||
|
|
||||||
|
rtp_free_msg(NULL, message);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline__ int toxav_decode_audio ( ToxAv* av, const uint8_t* payload, uint16_t length, int frame_size, short int* dest )
|
||||||
|
{
|
||||||
|
if ( !dest ) return ErrorInternal;
|
||||||
|
|
||||||
|
return opus_decode(av->cs->audio_decoder, payload, length, dest, frame_size, payload ? 0 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline__ int toxav_encode_audio ( ToxAv* av, const short int* frame, int frame_size, uint8_t* dest )
|
||||||
|
{
|
||||||
|
if ( !dest )
|
||||||
|
return ErrorInternal;
|
||||||
|
|
||||||
|
return opus_encode(av->cs->audio_encoder, frame, frame_size, dest, RTP_PAYLOAD_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int toxav_get_peer_transmission_type ( 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->type_peer[peer];
|
||||||
|
}
|
||||||
|
|
||||||
|
void* toxav_get_agent_handler ( ToxAv* av )
|
||||||
|
{
|
||||||
|
return av->agent_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Only temporary */
|
||||||
|
void* get_cs_temp(ToxAv* av)
|
||||||
|
{
|
||||||
|
return av->cs;
|
||||||
|
}
|
129
toxav/toxav.h
Normal file
129
toxav/toxav.h
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
/** toxav.h
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Report bugs/suggestions to me ( mannol ) at either #tox-dev @ freenode.net:6667 or
|
||||||
|
* my email: eniz_vukovic@hotmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __TOXAV
|
||||||
|
#define __TOXAV
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
typedef void* ( *ToxAVCallback ) ( void* arg );
|
||||||
|
typedef struct _ToxAv ToxAv;
|
||||||
|
|
||||||
|
#ifndef __TOX_DEFINED__
|
||||||
|
#define __TOX_DEFINED__
|
||||||
|
typedef struct Tox Tox;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RTP_PAYLOAD_SIZE 10400
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callbacks ids that handle the call states
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/* Requests */
|
||||||
|
OnInvite,
|
||||||
|
OnStart,
|
||||||
|
OnCancel,
|
||||||
|
OnReject,
|
||||||
|
OnEnd,
|
||||||
|
|
||||||
|
/* Responses */
|
||||||
|
OnRinging,
|
||||||
|
OnStarting,
|
||||||
|
OnEnding,
|
||||||
|
|
||||||
|
/* Protocol */
|
||||||
|
OnError,
|
||||||
|
OnTimeout
|
||||||
|
|
||||||
|
} ToxAvCallbackID;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Call type identifier.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
TypeAudio = 70,
|
||||||
|
TypeVideo
|
||||||
|
} ToxAvCallType;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ErrorNone = 0,
|
||||||
|
ErrorInternal = -1, /* Internal error */
|
||||||
|
ErrorAlreadyInCall = -2, /* Already has an active call */
|
||||||
|
ErrorNoCall = -3, /* Trying to perform call action while not in a call */
|
||||||
|
ErrorInvalidState = -4, /* Trying to perform call action while in invalid state*/
|
||||||
|
ErrorNoRtpSession = -5, /* Trying to perform rtp action on invalid session */
|
||||||
|
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() */
|
||||||
|
|
||||||
|
} ToxAvError;
|
||||||
|
|
||||||
|
|
||||||
|
ToxAv* toxav_new(Tox* messenger, void* useragent, const char* ua_name);
|
||||||
|
void toxav_kill(ToxAv* av);
|
||||||
|
|
||||||
|
void toxav_register_callstate_callback (ToxAVCallback callback, ToxAvCallbackID id);
|
||||||
|
|
||||||
|
|
||||||
|
int toxav_call(ToxAv* av, int user, ToxAvCallType call_type, int ringing_seconds);
|
||||||
|
int toxav_hangup(ToxAv* av);
|
||||||
|
int toxav_answer(ToxAv* av, ToxAvCallType call_type );
|
||||||
|
int toxav_reject(ToxAv* av, const char* reason);
|
||||||
|
int toxav_cancel(ToxAv* av, const char* reason);
|
||||||
|
int toxav_stop_call(ToxAv* av);
|
||||||
|
|
||||||
|
int toxav_prepare_transmission(ToxAv* av);
|
||||||
|
int toxav_kill_transmission(ToxAv* av);
|
||||||
|
|
||||||
|
|
||||||
|
int toxav_send_rtp_payload(ToxAv* av, ToxAvCallType type, const uint8_t* payload, uint16_t length);
|
||||||
|
|
||||||
|
/* Return length of received packet. Returns 0 if nothing recved. Dest has to have
|
||||||
|
* MAX_RTP_PAYLOAD_SIZE space available. Returns -1 if packet is not ready (ready < 1) for deque.
|
||||||
|
* For video packets set 'ready' at _any_ value.
|
||||||
|
*/
|
||||||
|
int toxav_recv_rtp_payload(ToxAv* av, ToxAvCallType type, int ready, uint8_t* dest);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int toxav_decode_audio( ToxAv* av, const uint8_t* payload, uint16_t length, int frame_size, short int* dest );
|
||||||
|
|
||||||
|
/* Please make sure 'dest' has enough storage for RTP_PAYLOAD_SIZE length of data */
|
||||||
|
int toxav_encode_audio( ToxAv* av, const short int* frame, int frame_size, uint8_t* dest );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int toxav_get_peer_transmission_type ( ToxAv* av, int peer );
|
||||||
|
void* toxav_get_agent_handler ( ToxAv* av );
|
||||||
|
|
||||||
|
/* Use this to get handle of CodecState from ToxAv struct */
|
||||||
|
void* get_cs_temp( ToxAv* av );
|
||||||
|
#endif /* __TOXAV */
|
Loading…
Reference in New Issue
Block a user