Video works now

This commit is contained in:
mannol 2015-04-08 01:00:19 +02:00
parent bf9f7e2ae8
commit 9c003c9dd2
6 changed files with 227 additions and 164 deletions

View File

@ -51,8 +51,8 @@
#define TEST_REJECT 0
#define TEST_CANCEL 0
#define TEST_MUTE_UNMUTE 0
#define TEST_TRANSFER_A 0
#define TEST_TRANSFER_V 1
#define TEST_TRANSFER_A 1
#define TEST_TRANSFER_V 0
typedef struct {
@ -128,7 +128,6 @@ void t_toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number,
IplImage* header = cvCreateImageHeader(sz, 1, 3);
IplImage* img = cvGetImage(&mat, header);
cvShowImage(vdout, img);
cvWaitKey(1);
free(img_data);
}
void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
@ -139,7 +138,7 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
void *user_data)
{
uint32_t bufid;
int32_t processed, queued;
int32_t processed = 0, queued = 16;
alGetSourcei(adout, AL_BUFFERS_PROCESSED, &processed);
alGetSourcei(adout, AL_BUFFERS_QUEUED, &queued);
@ -147,12 +146,12 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
uint32_t bufids[processed];
alSourceUnqueueBuffers(adout, processed, bufids);
alDeleteBuffers(processed - 1, bufids + 1);
bufid = bufids[0];
// bufid = bufids[0];
}
else if(queued < 16)
// else if(queued < 16)
alGenBuffers(1, &bufid);
else
return;
// else
// return;
alBufferData(bufid, channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16,
@ -246,22 +245,27 @@ int iterate_tox(Tox* bootstrap, ToxAV* AliceAV, ToxAV* BobAV)
tox_do(toxav_get_tox(AliceAV));
tox_do(toxav_get_tox(BobAV));
uint32_t rc = MIN(tox_do_interval(toxav_get_tox(AliceAV)), tox_do_interval(toxav_get_tox(BobAV)));
c_sleep(rc);
return rc;
return MIN(tox_do_interval(toxav_get_tox(AliceAV)), tox_do_interval(toxav_get_tox(BobAV)));
}
void* iterate_toxav (void * data)
{
struct toxav_thread_data* data_cast = data;
// cvNamedWindow(vdout, CV_WINDOW_AUTOSIZE);
while (data_cast->sig == 0) {
toxav_iterate(data_cast->AliceAV);
toxav_iterate(data_cast->BobAV);
// c_sleep(1);
int rc = MIN(toxav_iteration_interval(data_cast->AliceAV), toxav_iteration_interval(data_cast->BobAV));
printf("\rToxAV interval: %d ", rc);
fflush(stdout);
cvWaitKey(rc);
}
data_cast->sig = 1;
cvDestroyWindow(vdout);
// cvDestroyWindow(vdout);
pthread_exit(NULL);
}
@ -314,19 +318,8 @@ ALCdevice* open_audio_device(const char* audio_out_dev_name)
ALCcontext* out_ctx = alcCreateContext(rc, NULL);
alcMakeContextCurrent(out_ctx);
uint32_t buffers[10];
alGenBuffers(10, buffers);
alGenSources((uint32_t)1, &adout);
alSourcei(adout, AL_LOOPING, AL_FALSE);
int16_t zeros[10000];
memset(zeros, 0, sizeof(zeros));
int i;
for ( i = 0; i < 10; ++i )
alBufferData(buffers[i], AL_FORMAT_STEREO16, zeros, sizeof(zeros), 48000);
alSourceQueueBuffers(adout, 10, buffers);
alSourcePlay(adout);
return rc;
@ -351,8 +344,10 @@ int print_audio_devices()
int print_help (const char* name)
{
printf("Usage: %s -[a:v:o:dh]\n"
"-a <path> video input file\n"
"-a <path> audio input file\n"
"-b <ms> audio frame duration\n"
"-v <path> video input file\n"
"-x <ms> video frame duration\n"
"-o <idx> output audio device index\n"
"-d print output audio devices\n"
"-h print this help\n", name);
@ -363,7 +358,6 @@ int print_help (const char* name)
int main (int argc, char** argv)
{
cvNamedWindow(vdout, CV_WINDOW_AUTOSIZE);
struct stat st;
/* AV files for testing */
@ -371,14 +365,35 @@ int main (int argc, char** argv)
const char* vf_name = NULL;
long audio_out_dev_idx = 0;
/* Pasre settings */
CHECK_ARG: switch (getopt(argc, argv, "a:v:o:dh")) {
int32_t audio_frame_duration = 20;
int32_t video_frame_duration = 10;
/* Parse settings */
CHECK_ARG: switch (getopt(argc, argv, "a:b:v:x:o:dh")) {
case 'a':
af_name = optarg;
goto CHECK_ARG;
case 'b':{
char *d;
audio_frame_duration = strtol(optarg, &d, 10);
if (*d) {
printf("Invalid value for argument: 'b'");
exit(1);
}
goto CHECK_ARG;
}
case 'v':
vf_name = optarg;
goto CHECK_ARG;
case 'x':{
char *d;
video_frame_duration = strtol(optarg, &d, 10);
if (*d) {
printf("Invalid value for argument: 'x'");
exit(1);
}
goto CHECK_ARG;
}
case 'o': {
char *d;
audio_out_dev_idx = strtol(optarg, &d, 10);
@ -434,7 +449,40 @@ int main (int argc, char** argv)
printf("Using audio file: %s\n", af_name);
printf("Using video file: %s\n", vf_name);
if (0) {
/* Open audio file */
SF_INFO af_info;
SNDFILE* af_handle = sf_open(af_name, SFM_READ, &af_info);
if (af_handle == NULL)
{
printf("Failed to open the file.\n");
exit(1);
}
ALCdevice* audio_out_device = open_audio_device(audio_out_dev_name);
int16_t PCM[5760];
time_t start_time = time(NULL);
time_t expected_time = af_info.frames / af_info.samplerate + 2;
printf("Sample rate %d\n", af_info.samplerate);
while ( start_time + expected_time > time(NULL) ) {
int frame_size = (af_info.samplerate * audio_frame_duration / 1000) * af_info.channels;
int64_t count = sf_read_short(af_handle, PCM, frame_size);
if (count > 0)
t_toxav_receive_audio_frame_cb(NULL, 0, PCM, count, af_info.channels, af_info.samplerate, NULL);
c_sleep(audio_frame_duration);
}
printf("Played file in: %lu\n", time(NULL) - start_time);
alcCloseDevice(audio_out_device);
sf_close(af_handle);
return 0;
}
/* START TOX NETWORK */
Tox *bootstrap;
@ -714,8 +762,6 @@ int main (int argc, char** argv)
}
ALCdevice* audio_out_device = open_audio_device(audio_out_dev_name);
uint32_t frame_duration = 10;
int16_t PCM[5760];
time_t start_time = time(NULL);
@ -724,8 +770,8 @@ int main (int argc, char** argv)
/* Start decode thread */
struct toxav_thread_data data = {
.AliceAV = AliceAV,
.BobAV = BobAV,
.AliceAV = AliceAV,
.BobAV = BobAV,
.sig = 0
};
@ -733,8 +779,9 @@ int main (int argc, char** argv)
pthread_create(&dect, NULL, iterate_toxav, &data);
pthread_detach(dect);
printf("Sample rate %d\n", af_info.samplerate);
while ( start_time + expected_time > time(NULL) ) {
int frame_size = (af_info.samplerate * frame_duration / 1000) * af_info.channels;
int frame_size = (af_info.samplerate * audio_frame_duration / 1000) * af_info.channels;
int64_t count = sf_read_short(af_handle, PCM, frame_size);
if (count > 0) {
@ -746,7 +793,7 @@ int main (int argc, char** argv)
}
}
iterate_tox(bootstrap, AliceAV, BobAV);
// c_sleep(frame_duration);
c_sleep(audio_frame_duration);
}
@ -770,7 +817,8 @@ int main (int argc, char** argv)
/* Stop decode thread */
data.sig = -1;
while(data.sig != 1);
while(data.sig != 1)
pthread_yield();
printf("Success!");
}
@ -824,13 +872,14 @@ int main (int argc, char** argv)
}
time_t start_time = time(NULL);
while(start_time + 6 > time(NULL)) {
while(start_time + 90 > time(NULL)) {
IplImage* frame = cvQueryFrame( capture );
if (!frame)
break;
send_opencv_img(AliceAV, 0, frame);
iterate_tox(bootstrap, AliceAV, BobAV);
c_sleep(video_frame_duration);
}
cvReleaseCapture(&capture);
@ -849,9 +898,10 @@ int main (int argc, char** argv)
assert(BobCC.state == TOXAV_CALL_STATE_END);
/* Stop decode thread */
printf("Stopping decode thread");
printf("Stopping decode thread\n");
data.sig = -1;
while(data.sig != 1);
while(data.sig != 1)
pthread_yield();
printf("Success!");
}

View File

@ -38,7 +38,7 @@
#include "rtp.h"
#include "codec.h"
#define DEFAULT_JBUF 3
#define DEFAULT_JBUF 6
/* Good quality encode. */
#define MAX_DECODE_TIME_US 0
@ -324,17 +324,17 @@ void cs_do(CSession *cs)
int success = 0;
pthread_mutex_lock(cs->queue_mutex);
LOGGED_LOCK(cs->queue_mutex);
/********************* AUDIO *********************/
if (cs->audio_decoder) { /* If receiving enabled */
if (cs->audio_decoder) {
RTPMessage *msg;
/* The maximum for 120 ms 48 KHz audio */
int16_t tmp[5760];
while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) {
pthread_mutex_unlock(cs->queue_mutex);
LOGGED_UNLOCK(cs->queue_mutex);
if (success == 2) {
LOGGER_DEBUG("OPUS correction");
@ -377,7 +377,7 @@ void cs_do(CSession *cs)
cs->last_packet_channel_count, cs->last_packet_sampling_rate, cs->acb.second);
}
pthread_mutex_lock(cs->queue_mutex);
LOGGED_LOCK(cs->queue_mutex);
}
}
@ -387,7 +387,7 @@ void cs_do(CSession *cs)
buffer_read(cs->vbuf_raw, &p);
/* Leave space for (possibly) other thread to queue more data after we read it here */
pthread_mutex_unlock(cs->queue_mutex);
LOGGED_UNLOCK(cs->queue_mutex);
rc = vpx_codec_decode(cs->v_decoder, p->data, p->size, NULL, MAX_DECODE_TIME_US);
free(p);
@ -411,7 +411,7 @@ void cs_do(CSession *cs)
return;
}
pthread_mutex_unlock(cs->queue_mutex);
LOGGED_UNLOCK(cs->queue_mutex);
}
CSession *cs_new(uint32_t peer_video_frame_piece_size)
@ -423,7 +423,7 @@ CSession *cs_new(uint32_t peer_video_frame_piece_size)
return NULL;
}
if (pthread_mutex_init(cs->queue_mutex, NULL) != 0) {
if (create_recursive_mutex(cs->queue_mutex) != 0) {
LOGGER_WARNING("Failed to create recursive mutex!");
free(cs);
return NULL;
@ -481,6 +481,8 @@ CSession *cs_new(uint32_t peer_video_frame_piece_size)
if ( !(cs->split_video_frame = calloc(VIDEOFRAME_PIECE_SIZE + VIDEOFRAME_HEADER_SIZE, 1)) )
goto FAILURE;
cs->linfts = current_time_monotonic();
cs->lcfd = 10;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* Initialize encoders with default values */
@ -621,6 +623,8 @@ int cs_reconfigure_audio_encoder(CSession* cs, int32_t bitrate, int32_t sampling
cs->last_encoding_bitrate = bitrate;
cs->last_encoding_sampling_rate = sampling_rate;
cs->last_encoding_channel_count = channels;
LOGGER_DEBUG ("Reconfigured audio encoder br: %d sr: %d cc:%d", bitrate, sampling_rate, channels);
return 0;
}
@ -628,9 +632,6 @@ int cs_reconfigure_audio_encoder(CSession* cs, int32_t bitrate, int32_t sampling
/* Called from RTP */
void queue_message(RTPSession *session, RTPMessage *msg)
{
/* This function is unregistered during call termination befor destroying
* Codec session so no need to check for validity of cs TODO properly check video cycle
*/
CSession *cs = session->cs;
if (!cs)
@ -638,9 +639,9 @@ void queue_message(RTPSession *session, RTPMessage *msg)
/* Audio */
if (session->payload_type == rtp_TypeAudio % 128) {
pthread_mutex_lock(cs->queue_mutex);
LOGGED_LOCK(cs->queue_mutex);
int ret = jbuf_write(cs->j_buf, msg);
pthread_mutex_unlock(cs->queue_mutex);
LOGGED_UNLOCK(cs->queue_mutex);
if (ret == -1) {
rtp_free_msg(NULL, msg);
@ -662,7 +663,7 @@ void queue_message(RTPSession *session, RTPMessage *msg)
Payload *p = malloc(sizeof(Payload) + cs->frame_size);
if (p) {
pthread_mutex_lock(cs->queue_mutex);
LOGGED_LOCK(cs->queue_mutex);
if (buffer_full(cs->vbuf_raw)) {
LOGGER_DEBUG("Dropped video frame");
@ -673,15 +674,19 @@ void queue_message(RTPSession *session, RTPMessage *msg)
p->size = cs->frame_size;
memcpy(p->data, cs->frame_buf, cs->frame_size);
}
/* Calculate time took for peer to send us this frame */
uint32_t t_lcfd = current_time_monotonic() - cs->linfts;
cs->lcfd = t_lcfd > 100 ? cs->lcfd : t_lcfd;
cs->linfts = current_time_monotonic();
buffer_write(cs->vbuf_raw, p);
pthread_mutex_unlock(cs->queue_mutex);
LOGGED_UNLOCK(cs->queue_mutex);
} else {
LOGGER_WARNING("Allocation failed! Program might misbehave!");
goto end;
}
cs->last_timestamp = msg->header->timestamp;
cs->frameid_in = packet[0];
memset(cs->frame_buf, 0, cs->frame_size);
cs->frame_size = 0;

View File

@ -61,8 +61,9 @@ typedef struct CSession_s {
uint8_t *frame_buf; /* buffer for split video payloads */
uint32_t frame_size; /* largest address written to in frame_buf for current input frame */
uint8_t frameid_in, frameid_out; /* id of input and output video frame */
uint32_t last_timestamp; /* calculating cycles */
uint64_t linfts; /* Last received frame time stamp */
uint32_t lcfd; /* Last calculated frame duration for incoming video payload */
/* Limits */
uint32_t peer_video_frame_piece_size;

View File

@ -99,9 +99,9 @@ void handle_msi_packet ( Messenger *m, int friend_id, const uint8_t *data, uint1
*/
void msi_register_callback ( MSISession *session, MSICallbackType callback, MSICallbackID id)
{
pthread_mutex_lock(session->mutex);
LOGGED_LOCK(session->mutex);
session->callbacks[id] = callback;
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
}
MSISession *msi_new ( Messenger *messenger )
{
@ -141,7 +141,7 @@ int msi_kill ( MSISession *session )
}
m_callback_msi_packet((struct Messenger *) session->messenger, NULL, NULL);
pthread_mutex_lock(session->mutex);
LOGGED_LOCK(session->mutex);
if (session->calls) {
MSIMessage msg;
@ -154,7 +154,7 @@ int msi_kill ( MSISession *session )
}
}
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
pthread_mutex_destroy(session->mutex);
LOGGER_DEBUG("Terminated session: %p", session);
@ -165,17 +165,17 @@ int msi_invite ( MSISession *session, MSICall **call, uint32_t friend_id, uint8_
{
LOGGER_DEBUG("Session: %p Inviting friend: %u", session, friend_id);
pthread_mutex_lock(session->mutex);
LOGGED_LOCK(session->mutex);
if (get_call(session, friend_id) != NULL) {
LOGGER_ERROR("Already in a call");
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return -1;
}
(*call) = new_call ( session, friend_id );
if ( *call == NULL ) {
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return -1;
}
@ -195,7 +195,7 @@ int msi_invite ( MSISession *session, MSICall **call, uint32_t friend_id, uint8_
(*call)->state = msi_CallRequesting;
LOGGER_DEBUG("Invite sent");
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return 0;
}
int msi_hangup ( MSICall* call )
@ -203,7 +203,7 @@ int msi_hangup ( MSICall* call )
LOGGER_DEBUG("Session: %p Hanging up call with friend: %u", call->session, call->friend_id);
MSISession* session = call->session;
pthread_mutex_lock(session->mutex);
LOGGED_LOCK(session->mutex);
MSIMessage msg;
msg_init(&msg, requ_pop);
@ -211,7 +211,7 @@ int msi_hangup ( MSICall* call )
send_message ( session->messenger, call->friend_id, &msg );
kill_call(call);
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return 0;
}
int msi_answer ( MSICall* call, uint8_t capabilities )
@ -219,13 +219,13 @@ int msi_answer ( MSICall* call, uint8_t capabilities )
LOGGER_DEBUG("Session: %p Answering call from: %u", call->session, call->friend_id);
MSISession* session = call->session;
pthread_mutex_lock(session->mutex);
LOGGED_LOCK(session->mutex);
if ( call->state != msi_CallRequested ) {
/* Though sending in invalid state will not cause anything wierd
* Its better to not do it like a maniac */
LOGGER_ERROR("Call is in invalid state!");
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return -1;
}
@ -243,7 +243,7 @@ int msi_answer ( MSICall* call, uint8_t capabilities )
send_message ( session->messenger, call->friend_id, &msg );
call->state = msi_CallActive;
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return 0;
}
@ -252,7 +252,7 @@ int msi_change_capabilities( MSICall* call, uint8_t capabilities )
LOGGER_DEBUG("Session: %p Trying to change capabilities to friend %u", call->session, call->friend_id);
MSISession* session = call->session;
pthread_mutex_lock(session->mutex);
LOGGED_LOCK(session->mutex);
if ( call->state != msi_CallActive ) {
/* Sending capabilities change can cause error on other side if
@ -263,7 +263,7 @@ int msi_change_capabilities( MSICall* call, uint8_t capabilities )
* like new. TODO: explain this better
*/
LOGGER_ERROR("Call is in invalid state!");
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return -1;
}
@ -277,7 +277,7 @@ int msi_change_capabilities( MSICall* call, uint8_t capabilities )
send_message ( call->session->messenger, call->friend_id, &msg );
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return 0;
}
@ -581,17 +581,17 @@ void on_peer_status(Messenger *m, int friend_id, uint8_t status, void *data)
case 0: { /* Friend is now offline */
LOGGER_DEBUG("Friend %d is now offline", friend_id);
pthread_mutex_lock(session->mutex);
LOGGED_LOCK(session->mutex);
MSICall* call = get_call(session, friend_id);
if (call == NULL) {
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return;
}
invoke_callback(call, msi_OnPeerTimeout); /* Failure is ignored */
kill_call(call);
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
}
break;
@ -759,20 +759,20 @@ void handle_msi_packet ( Messenger *m, int friend_id, const uint8_t *data, uint1
LOGGER_DEBUG("Successfully parsed message");
}
pthread_mutex_lock(session->mutex);
LOGGED_LOCK(session->mutex);
MSICall *call = get_call(session, friend_id);
if (call == NULL) {
if (msg.request.value != requ_push) {
send_error(m, friend_id, msi_EStrayMessage);
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return;
}
call = new_call(session, friend_id);
if (call == NULL) {
send_error(m, friend_id, msi_ESystem);
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
return;
}
}
@ -782,5 +782,5 @@ void handle_msi_packet ( Messenger *m, int friend_id, const uint8_t *data, uint1
else
handle_pop(call, &msg); /* always kills the call */
pthread_mutex_unlock(session->mutex);
LOGGED_UNLOCK(session->mutex);
}

View File

@ -29,15 +29,15 @@
#include "../toxcore/Messenger.h"
#define LOGGED_LOCK(mutex) do { \
LOGGER_DEBUG("Locking mutex: %p", mutex);\
/*LOGGER_DEBUG("Locking mutex: %p", mutex);*/\
pthread_mutex_lock(mutex);\
LOGGER_DEBUG("Locked mutex: %p", mutex);\
/*LOGGER_DEBUG("Locked mutex: %p", mutex);*/\
} while(0)
#define LOGGED_UNLOCK(mutex) do { \
LOGGER_DEBUG("Unlocking mutex: %p", mutex);\
/*LOGGER_DEBUG("Unlocking mutex: %p", mutex);*/\
pthread_mutex_unlock(mutex);\
LOGGER_DEBUG("Unlocked mutex: %p", mutex);\
/*LOGGER_DEBUG("Unlocked mutex: %p", mutex);*/\
} while(0)
#define MAX_SEQU_NUM 65535

View File

@ -129,8 +129,7 @@ ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
goto FAILURE;
}
// if (create_recursive_mutex(av->mutex) == -1) {
if (pthread_mutex_init(av->mutex, NULL) == -1) {
if (create_recursive_mutex(av->mutex) != 0) {
LOGGER_WARNING("Mutex creation failed!");
rc = TOXAV_ERR_NEW_MALLOC;
goto FAILURE;
@ -174,7 +173,7 @@ void toxav_kill(ToxAV* av)
{
if (av == NULL)
return;
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
msi_kill(av->msi);
@ -187,7 +186,7 @@ void toxav_kill(ToxAV* av)
}
}
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
pthread_mutex_destroy(av->mutex);
free(av);
}
@ -205,9 +204,9 @@ uint32_t toxav_iteration_interval(const ToxAV* av)
void toxav_iterate(ToxAV* av)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
if (av->calls == NULL) {
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
return;
}
@ -215,20 +214,28 @@ void toxav_iterate(ToxAV* av)
uint32_t rc = 500;
ToxAVCall* i = av->calls[av->calls_head];
while (i) {
for (; i; i = i->next) {
if (i->active) {
pthread_mutex_lock(i->mutex_decoding);
pthread_mutex_unlock(av->mutex);
LOGGED_LOCK(i->mutex_decoding);
LOGGED_UNLOCK(av->mutex);
cs_do(i->cs);
rc = MIN(i->cs->last_packet_frame_duration, rc);
if (i->last_self_capabilities & msi_CapRAudio) /* Receiving audio */
rc = MIN(i->cs->last_packet_frame_duration, rc);
if (i->last_self_capabilities & msi_CapRVideo) /* Receiving video */
rc = MIN(i->cs->lcfd, rc);
pthread_mutex_lock(av->mutex);
pthread_mutex_unlock(i->mutex_decoding);
i = i->next;
uint32_t fid = i->friend_id;
LOGGED_UNLOCK(i->mutex_decoding);
LOGGED_LOCK(av->mutex);
/* In case this call is popped from container stop iteration */
if (call_get(av, fid) != i)
break;
}
}
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
av->interval = rc < av->dmssa ? 0 : (rc - av->dmssa);
av->dmsst += current_time_monotonic() - start;
@ -242,10 +249,10 @@ void toxav_iterate(ToxAV* av)
bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL* error)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
ToxAVCall* call = call_new(av, friend_number, error);
if (call == NULL) {
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
return false;
}
@ -261,27 +268,27 @@ bool toxav_call(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint
call_remove(call);
if (error)
*error = TOXAV_ERR_CALL_MALLOC;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
return false;
}
call->msi_call->av_call = call;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
return true;
}
void toxav_callback_call(ToxAV* av, toxav_call_cb* function, void* user_data)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
av->ccb.first = function;
av->ccb.second = user_data;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
}
bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER* error)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
TOXAV_ERR_ANSWER rc = TOXAV_ERR_ANSWER_OK;
if (m_friend_exists(av->m, friend_number) == 0) {
@ -320,7 +327,7 @@ bool toxav_answer(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, ui
END:
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
if (error)
*error = rc;
@ -330,15 +337,15 @@ END:
void toxav_callback_call_state(ToxAV* av, toxav_call_state_cb* function, void* user_data)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
av->scb.first = function;
av->scb.second = user_data;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
}
bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL* error)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
TOXAV_ERR_CALL_CONTROL rc = TOXAV_ERR_CALL_CONTROL_OK;
if (m_friend_exists(av->m, friend_number) == 0) {
@ -474,7 +481,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
}
END:
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
if (error)
*error = rc;
@ -497,17 +504,17 @@ bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_
goto END;
}
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
call = call_get(av, friend_number);
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL;
goto END;
}
/* NOTE: no need to lock*/
call->audio_bit_rate = audio_bit_rate;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
END:
if (error)
@ -531,17 +538,17 @@ bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_
goto END;
}
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
call = call_get(av, friend_number);
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL;
goto END;
}
/* NOTE: no need to lock*/
call->video_bit_rate = video_bit_rate;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
END:
if (error)
@ -552,10 +559,10 @@ END:
void toxav_callback_video_frame_request(ToxAV* av, toxav_video_frame_request_cb* function, void* user_data)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
av->rvcb.first = function;
av->rvcb.second = user_data;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
}
bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, TOXAV_ERR_SEND_FRAME* error)
@ -568,25 +575,25 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
goto END;
}
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
call = call_get(av, friend_number);
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
goto END;
}
pthread_mutex_lock(call->mutex_video_sending);
pthread_mutex_unlock(av->mutex);
LOGGED_LOCK(call->mutex_video_sending);
LOGGED_UNLOCK(av->mutex);
if ( y == NULL || u == NULL || v == NULL ) {
pthread_mutex_unlock(call->mutex_video_sending);
LOGGED_UNLOCK(call->mutex_video_sending);
rc = TOXAV_ERR_SEND_FRAME_NULL;
goto END;
}
if ( cs_reconfigure_video_encoder(call->cs, call->video_bit_rate, width, height) != 0 ) {
pthread_mutex_unlock(call->mutex_video_sending);
LOGGED_UNLOCK(call->mutex_video_sending);
rc = TOXAV_ERR_SEND_FRAME_INVALID;
goto END;
}
@ -608,7 +615,7 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
vpx_img_free(&img);
if ( vrc != VPX_CODEC_OK) {
pthread_mutex_unlock(call->mutex_video_sending);
LOGGED_UNLOCK(call->mutex_video_sending);
LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(vrc));
rc = TOXAV_ERR_SEND_FRAME_INVALID;
goto END;
@ -639,7 +646,7 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
iter = cs_iterate_split_video_frame(call->cs, &part_size);
if (rtp_send_msg(call->rtps[video_index], iter, part_size) < 0) {
pthread_mutex_unlock(call->mutex_video_sending);
LOGGED_UNLOCK(call->mutex_video_sending);
LOGGER_WARNING("Could not send video frame: %s\n", strerror(errno));
goto END;
}
@ -648,7 +655,7 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
}
}
pthread_mutex_unlock(call->mutex_video_sending);
LOGGED_UNLOCK(call->mutex_video_sending);
END:
if (error)
@ -659,10 +666,10 @@ END:
void toxav_callback_audio_frame_request(ToxAV* av, toxav_audio_frame_request_cb* function, void* user_data)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
av->racb.first = function;
av->racb.second = user_data;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
}
bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME* error)
@ -675,32 +682,32 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
goto END;
}
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
call = call_get(av, friend_number);
if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
goto END;
}
pthread_mutex_lock(call->mutex_audio_sending);
pthread_mutex_unlock(av->mutex);
LOGGED_LOCK(call->mutex_audio_sending);
LOGGED_UNLOCK(av->mutex);
if ( pcm == NULL ) {
pthread_mutex_unlock(call->mutex_audio_sending);
LOGGED_UNLOCK(call->mutex_audio_sending);
rc = TOXAV_ERR_SEND_FRAME_NULL;
goto END;
}
if ( channels > 2 ) {
pthread_mutex_unlock(call->mutex_audio_sending);
LOGGED_UNLOCK(call->mutex_audio_sending);
rc = TOXAV_ERR_SEND_FRAME_INVALID;
goto END;
}
{ /* Encode and send */
if (cs_reconfigure_audio_encoder(call->cs, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
pthread_mutex_unlock(call->mutex_audio_sending);
LOGGED_UNLOCK(call->mutex_audio_sending);
rc = TOXAV_ERR_SEND_FRAME_INVALID;
goto END;
}
@ -711,7 +718,7 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
if (vrc < 0) {
LOGGER_WARNING("Failed to encode frame");
pthread_mutex_unlock(call->mutex_audio_sending);
LOGGED_UNLOCK(call->mutex_audio_sending);
rc = TOXAV_ERR_SEND_FRAME_INVALID;
goto END;
}
@ -722,7 +729,7 @@ bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pc
}
}
pthread_mutex_unlock(call->mutex_audio_sending);
LOGGED_UNLOCK(call->mutex_audio_sending);
END:
if (error)
@ -733,18 +740,18 @@ END:
void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
av->vcb.first = function;
av->vcb.second = user_data;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
}
void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* function, void* user_data)
{
pthread_mutex_lock(av->mutex);
LOGGED_LOCK(av->mutex);
av->acb.first = function;
av->acb.second = user_data;
pthread_mutex_unlock(av->mutex);
LOGGED_UNLOCK(av->mutex);
}
@ -756,12 +763,12 @@ void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb*
int callback_invite(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
pthread_mutex_lock(toxav->mutex);
LOGGED_LOCK(toxav->mutex);
ToxAVCall* av_call = call_new(toxav, call->friend_id, NULL);
if (av_call == NULL) {
LOGGER_WARNING("Failed to initialize call...");
pthread_mutex_unlock(toxav->mutex);
LOGGED_UNLOCK(toxav->mutex);
return -1;
}
@ -772,41 +779,41 @@ int callback_invite(void* toxav_inst, MSICall* call)
toxav->ccb.first(toxav, call->friend_id, call->peer_capabilities & msi_CapSAudio,
call->peer_capabilities & msi_CapSVideo, toxav->ccb.second);
pthread_mutex_unlock(toxav->mutex);
LOGGED_UNLOCK(toxav->mutex);
return 0;
}
int callback_start(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
pthread_mutex_lock(toxav->mutex);
LOGGED_LOCK(toxav->mutex);
ToxAVCall* av_call = call_get(toxav, call->friend_id);
if (av_call == NULL) {
/* Should this ever happen? */
pthread_mutex_unlock(toxav->mutex);
LOGGED_UNLOCK(toxav->mutex);
return -1;
}
if (!call_prepare_transmission(av_call)) {
callback_error(toxav_inst, call);
call_remove(av_call);
pthread_mutex_unlock(toxav->mutex);
LOGGED_UNLOCK(toxav->mutex);
return -1;
}
if (toxav->scb.first)
toxav->scb.first(toxav, call->friend_id, call->peer_capabilities, toxav->scb.second);
pthread_mutex_unlock(toxav->mutex);
LOGGED_UNLOCK(toxav->mutex);
return 0;
}
int callback_end(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
pthread_mutex_lock(toxav->mutex);
LOGGED_LOCK(toxav->mutex);
if (toxav->scb.first)
toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second);
@ -814,14 +821,14 @@ int callback_end(void* toxav_inst, MSICall* call)
call_kill_transmission(call->av_call);
call_remove(call->av_call);
pthread_mutex_unlock(toxav->mutex);
LOGGED_UNLOCK(toxav->mutex);
return 0;
}
int callback_error(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
pthread_mutex_lock(toxav->mutex);
LOGGED_LOCK(toxav->mutex);
if (toxav->scb.first)
toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second);
@ -829,21 +836,21 @@ int callback_error(void* toxav_inst, MSICall* call)
call_kill_transmission(call->av_call);
call_remove(call->av_call);
pthread_mutex_unlock(toxav->mutex);
LOGGED_UNLOCK(toxav->mutex);
return 0;
}
int callback_capabilites(void* toxav_inst, MSICall* call)
{
ToxAV* toxav = toxav_inst;
pthread_mutex_lock(toxav->mutex);
LOGGED_LOCK(toxav->mutex);
/* TODO modify cs? */
if (toxav->scb.first)
toxav->scb.first(toxav, call->friend_id, call->peer_capabilities, toxav->scb.second);
pthread_mutex_unlock(toxav->mutex);
LOGGED_UNLOCK(toxav->mutex);
return 0;
}
@ -969,14 +976,14 @@ bool call_prepare_transmission(ToxAVCall* call)
return true;
}
if (pthread_mutex_init(call->mutex_audio_sending, NULL) != 0)
if (create_recursive_mutex(call->mutex_audio_sending) != 0)
return false;
if (pthread_mutex_init(call->mutex_video_sending, NULL) != 0) {
if (create_recursive_mutex(call->mutex_video_sending) != 0) {
goto AUDIO_SENDING_MUTEX_CLEANUP;
}
if (pthread_mutex_init(call->mutex_decoding, NULL) != 0) {
if (create_recursive_mutex(call->mutex_decoding) != 0) {
goto VIDEO_SENDING_MUTEX_CLEANUP;
}
@ -1058,12 +1065,12 @@ void call_kill_transmission(ToxAVCall* call)
rtp_kill(call->rtps[video_index]);
call->rtps[video_index] = NULL;
pthread_mutex_lock(call->mutex_audio_sending);
pthread_mutex_unlock(call->mutex_audio_sending);
pthread_mutex_lock(call->mutex_video_sending);
pthread_mutex_unlock(call->mutex_video_sending);
pthread_mutex_lock(call->mutex_decoding);
pthread_mutex_unlock(call->mutex_decoding);
LOGGED_LOCK(call->mutex_audio_sending);
LOGGED_UNLOCK(call->mutex_audio_sending);
LOGGED_LOCK(call->mutex_video_sending);
LOGGED_UNLOCK(call->mutex_video_sending);
LOGGED_LOCK(call->mutex_decoding);
LOGGED_UNLOCK(call->mutex_decoding);
cs_kill(call->cs);
call->cs = NULL;