mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge branch 'mannol1-master'
This commit is contained in:
commit
aa1194ab3e
|
@ -4,9 +4,7 @@ lib_LTLIBRARIES += libtoxav.la
|
|||
libtoxav_la_include_HEADERS = ../toxav/toxav.h
|
||||
libtoxav_la_includedir = $(includedir)/tox
|
||||
|
||||
libtoxav_la_SOURCES = ../toxav/event.h \
|
||||
../toxav/event.c \
|
||||
../toxav/rtp.h \
|
||||
libtoxav_la_SOURCES = ../toxav/rtp.h \
|
||||
../toxav/rtp.c \
|
||||
../toxav/msi.h \
|
||||
../toxav/msi.c \
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/** media.c
|
||||
/** codec.c
|
||||
*
|
||||
* Audio and video codec intitialization, encoding/decoding and playback
|
||||
*
|
||||
|
@ -212,7 +212,7 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
|
|||
vpx_codec_enc_cfg_t cfg;
|
||||
int rc = vpx_codec_enc_config_default(VIDEO_CODEC_ENCODER_INTERFACE, &cfg, 0);
|
||||
|
||||
if (rc) {
|
||||
if (rc != VPX_CODEC_OK) {
|
||||
LOGGER_ERROR("Failed to get config: %s", vpx_codec_err_to_string(rc));
|
||||
return -1;
|
||||
}
|
||||
|
@ -234,6 +234,12 @@ int init_video_encoder(CodecState *cs, uint16_t width, uint16_t height, uint32_t
|
|||
}
|
||||
|
||||
rc = vpx_codec_control(&cs->v_encoder, VP8E_SET_CPUUSED, 7);
|
||||
|
||||
if ( rc != VPX_CODEC_OK) {
|
||||
LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/** media.h
|
||||
/** codec.h
|
||||
*
|
||||
* Audio and video codec intitialization, encoding/decoding and playback
|
||||
*
|
||||
|
|
380
toxav/event.c
380
toxav/event.c
|
@ -1,380 +0,0 @@
|
|||
/** event.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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "../toxcore/network.h" /* current_time_monotonic() */
|
||||
#include "event.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define RUN_IN_THREAD(func, args) { pthread_t _tid; \
|
||||
pthread_create(&_tid, NULL, func, args); assert( pthread_detach(_tid) == 0 ); }
|
||||
|
||||
#define LOCK(event_handler) pthread_mutex_lock (&event_handler->mutex)
|
||||
#define UNLOCK(event_handler) pthread_mutex_unlock(&event_handler->mutex)
|
||||
|
||||
#define FREQUENCY 10000
|
||||
|
||||
#define inline__ inline __attribute__((always_inline))
|
||||
|
||||
|
||||
typedef struct _EventContainer {
|
||||
void *(*func)(void *);
|
||||
void *func_args;
|
||||
unsigned timeout;
|
||||
long long id;
|
||||
|
||||
} EventContainer;
|
||||
|
||||
typedef struct _EventHandler {
|
||||
EventContainer *timed_events;
|
||||
size_t timed_events_count;
|
||||
|
||||
int running;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
} EventHandler;
|
||||
|
||||
int throw_event( void *(func)(void *), void *arg );
|
||||
int reset_timer_event ( int id, uint32_t timeout );
|
||||
int throw_timer_event ( void *(func)(void *), void *arg, unsigned timeout);
|
||||
int cancel_timer_event ( int id );
|
||||
int execute_timer_event ( int id );
|
||||
|
||||
struct _Event event = {
|
||||
throw_event,
|
||||
/* reset_timer_event */ NULL,
|
||||
throw_timer_event,
|
||||
cancel_timer_event,
|
||||
/*execute_timer_event*/ NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* Random functions used by this file
|
||||
*/
|
||||
void clear_events (EventContainer **event_container, size_t *counter)
|
||||
{
|
||||
free(*event_container );
|
||||
|
||||
*event_container = NULL;
|
||||
*counter = 0;
|
||||
}
|
||||
|
||||
int pop_id ( EventContainer **event_container, size_t *counter, int id )
|
||||
{
|
||||
if ( !*event_container || !*counter || !id )
|
||||
return -1;
|
||||
|
||||
EventContainer *_it = *event_container;
|
||||
int i;
|
||||
|
||||
for ( i = *counter; i; -- i ) {
|
||||
if ( _it->id == id ) { /* Hit! */
|
||||
break;
|
||||
}
|
||||
|
||||
++_it;
|
||||
}
|
||||
|
||||
if ( i ) {
|
||||
for ( ; i; -- i ) {
|
||||
*_it = *(_it + 1);
|
||||
++_it;
|
||||
}
|
||||
|
||||
-- (*counter );
|
||||
|
||||
if ( !(*counter)) { /* Free and set to NULL */
|
||||
free(*event_container);
|
||||
*event_container = NULL;
|
||||
} else {
|
||||
void *_result = realloc(*event_container, sizeof(EventContainer) * (*counter )); /* resize */
|
||||
|
||||
|
||||
if ( _result != NULL ) {
|
||||
*event_container = _result;
|
||||
return 0;
|
||||
} else {
|
||||
/* Not sure what would happen next so abort execution.
|
||||
*/
|
||||
fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
|
||||
abort();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* not found here */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void push_event ( EventContainer **container, size_t *counter, void *(func)(void *), void *arg )
|
||||
{
|
||||
EventContainer *_new = realloc((*container ), sizeof(EventContainer) * ((*counter ) + 1));
|
||||
|
||||
if ( _new == NULL ) {
|
||||
/* Not sure what would happen next so abort execution.
|
||||
* TODO: This could notice the calling function
|
||||
* about realloc failing.
|
||||
*/
|
||||
fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
|
||||
abort();
|
||||
}
|
||||
|
||||
_new[*counter].func = func;
|
||||
_new[*counter].func_args = arg;
|
||||
_new[*counter].timeout = 0;
|
||||
_new[*counter].id = 0;
|
||||
|
||||
(*container) = _new;
|
||||
|
||||
(*counter )++;
|
||||
}
|
||||
|
||||
void reorder_events ( size_t counter, EventContainer *container, unsigned timeout )
|
||||
{
|
||||
if ( counter > 1 ) {
|
||||
|
||||
int i = counter - 1;
|
||||
|
||||
/* start from behind excluding last added member */
|
||||
EventContainer *_it = &container[i - 1];
|
||||
|
||||
EventContainer _last_added = container[i];
|
||||
|
||||
for ( ; i; --i ) {
|
||||
if ( _it->timeout > timeout ) {
|
||||
*(_it + 1) = *_it;
|
||||
*_it = _last_added;
|
||||
-- _it;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================= */
|
||||
|
||||
/* main poll for event execution */
|
||||
void *event_poll( void *arg )
|
||||
{
|
||||
EventHandler *_event_handler = arg;
|
||||
|
||||
while ( _event_handler->running ) {
|
||||
|
||||
LOCK( _event_handler );
|
||||
|
||||
if ( _event_handler->timed_events ) {
|
||||
|
||||
uint32_t _time = ((uint32_t)current_time_monotonic());
|
||||
|
||||
if ( _event_handler->timed_events[0].timeout < _time ) {
|
||||
|
||||
RUN_IN_THREAD ( _event_handler->timed_events[0].func,
|
||||
_event_handler->timed_events[0].func_args );
|
||||
|
||||
pop_id(&_event_handler->timed_events,
|
||||
&_event_handler->timed_events_count,
|
||||
_event_handler->timed_events[0].id);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
UNLOCK( _event_handler );
|
||||
|
||||
usleep(FREQUENCY);
|
||||
}
|
||||
|
||||
LOCK( _event_handler );
|
||||
|
||||
clear_events(&_event_handler->timed_events, &_event_handler->timed_events_count);
|
||||
|
||||
UNLOCK( _event_handler );
|
||||
|
||||
_event_handler->running = -1;
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
int throw_event( void *(func)(void *), void *arg )
|
||||
{
|
||||
pthread_t _tid;
|
||||
int _rc =
|
||||
pthread_create(&_tid, NULL, func, arg );
|
||||
|
||||
return (0 != _rc ) ? _rc : pthread_detach(_tid);
|
||||
}
|
||||
|
||||
EventHandler event_handler;
|
||||
|
||||
/* Place and order array of timers */
|
||||
int throw_timer_event ( void *(func)(void *), void *arg, unsigned timeout)
|
||||
{
|
||||
static int _unique_id = 1;
|
||||
|
||||
push_event(&event_handler.timed_events, &(event_handler.timed_events_count), func, arg );
|
||||
|
||||
size_t _counter = event_handler.timed_events_count;
|
||||
|
||||
event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)current_time_monotonic());
|
||||
event_handler.timed_events[_counter - 1].id = _unique_id;
|
||||
++_unique_id;
|
||||
|
||||
|
||||
/* reorder */
|
||||
|
||||
reorder_events(_counter, event_handler.timed_events, timeout );
|
||||
|
||||
return _unique_id - 1;
|
||||
}
|
||||
|
||||
int execute_timer_event ( int id )
|
||||
{
|
||||
int _status;
|
||||
|
||||
LOCK((&event_handler));
|
||||
EventContainer *_it = event_handler.timed_events;
|
||||
|
||||
int _i = event_handler.timed_events_count;
|
||||
|
||||
/* Find it and execute */
|
||||
for ( ; _i; _i-- ) {
|
||||
if ( _it->id == id ) {
|
||||
RUN_IN_THREAD ( _it->func, _it->func_args );
|
||||
break;
|
||||
}
|
||||
|
||||
++_it;
|
||||
}
|
||||
|
||||
/* Now remove it from the queue */
|
||||
|
||||
if ( _i ) {
|
||||
for ( ; _i; -- _i ) {
|
||||
*_it = *(_it + 1);
|
||||
++_it;
|
||||
}
|
||||
|
||||
-- event_handler.timed_events_count;
|
||||
|
||||
if ( !event_handler.timed_events_count ) { /* Free and set to null */
|
||||
free(event_handler.timed_events);
|
||||
event_handler.timed_events = NULL;
|
||||
} else {
|
||||
void *_result = realloc(event_handler.timed_events,
|
||||
sizeof(EventContainer) * event_handler.timed_events_count); /* resize */
|
||||
|
||||
if ( _result != NULL ) {
|
||||
event_handler.timed_events = _result;
|
||||
} else {
|
||||
/* Not sure what would happen next so abort execution.
|
||||
*/
|
||||
fprintf(stderr, "CRITICAL! Failed to reallocate memory in %s():%d, aborting...", __func__, __LINE__);
|
||||
abort();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_status = 0;
|
||||
|
||||
} else _status = -1;
|
||||
|
||||
UNLOCK((&event_handler));
|
||||
|
||||
return _status;
|
||||
}
|
||||
|
||||
int reset_timer_event ( int id, uint32_t timeout )
|
||||
{
|
||||
int _status;
|
||||
|
||||
LOCK((&event_handler));
|
||||
|
||||
EventContainer *_it = event_handler.timed_events;
|
||||
|
||||
int _i = event_handler.timed_events_count;
|
||||
|
||||
/* Find it and change */
|
||||
for ( ; _i; _i-- ) {
|
||||
if ( _it->id == id ) {
|
||||
_it->timeout = timeout + ((uint32_t)current_time_monotonic());
|
||||
break;
|
||||
}
|
||||
|
||||
++_it;
|
||||
}
|
||||
|
||||
_status = _i ? -1 : 0;
|
||||
|
||||
UNLOCK((&event_handler));
|
||||
|
||||
return _status;
|
||||
}
|
||||
|
||||
/* Remove timer from array */
|
||||
inline__ int cancel_timer_event ( int id )
|
||||
{
|
||||
return pop_id (&event_handler.timed_events, &event_handler.timed_events_count, id );
|
||||
}
|
||||
|
||||
|
||||
/* Initialization and termination of event polls
|
||||
* This will be run at the beginning and the end of the program execution.
|
||||
* I think that's the best way to do it.
|
||||
*/
|
||||
|
||||
void __attribute__((constructor)) init_event_poll ()
|
||||
{
|
||||
event_handler.timed_events = NULL;
|
||||
event_handler.timed_events_count = 0;
|
||||
|
||||
event_handler.running = 1;
|
||||
|
||||
pthread_mutex_init(&event_handler.mutex, NULL);
|
||||
|
||||
RUN_IN_THREAD(event_poll, &event_handler);
|
||||
}
|
||||
|
||||
/* NOTE: Do we need this? */
|
||||
void __attribute__((destructor)) terminate_event_poll()
|
||||
{
|
||||
/* Exit thread */
|
||||
event_handler.running = 0;
|
||||
|
||||
/* Give it enought time to exit */
|
||||
usleep(FREQUENCY * 2);
|
||||
|
||||
pthread_mutex_destroy( &event_handler.mutex );
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/** event.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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TOXEVENT
|
||||
#define __TOXEVENT
|
||||
|
||||
|
||||
/**
|
||||
* - Events are, in fact, ran in their own threads upon execution.
|
||||
* - Event handler is initialized at the start, before the main() function
|
||||
* and terminated after it's execution.
|
||||
* - Timers are checked for timeout every ~10000 ns.
|
||||
* - Timers can be canceled or ran immediately via
|
||||
* timer_release() or timer_now() functions.
|
||||
* - Timeout is measured in milliseconds.
|
||||
*
|
||||
* NOTE: timer_reset () and timer_now() are not tested nor usable atm
|
||||
*
|
||||
*/
|
||||
extern struct _Event {
|
||||
int (*rise) (void *( func ) ( void *), void *arg);
|
||||
int (*timer_reset ) ( int id, unsigned timeout );
|
||||
int (*timer_alloc) (void *( func ) ( void *), void *arg, unsigned timeout);
|
||||
int (*timer_release) (int id);
|
||||
int (*timer_now) ( int id );
|
||||
} event;
|
||||
|
||||
#endif /* _MSI__EVENT_H_ */
|
322
toxav/msi.c
322
toxav/msi.c
|
@ -115,7 +115,6 @@ static struct _Callbacks {
|
|||
|
||||
inline__ void invoke_callback(int32_t call_index, MSICallbackID id)
|
||||
{
|
||||
/*if ( callbacks[id].function ) event.rise ( callbacks[id].function, callbacks[id].data );*/
|
||||
if ( callbacks[id].function ) {
|
||||
LOGGER_DEBUG("Invoking callback function: %d", id);
|
||||
callbacks[id].function ( call_index, callbacks[id].data );
|
||||
|
@ -220,7 +219,7 @@ if ( *iterator != value_byte || size_con <= type_size_const) { return -1; } size
|
|||
iterator ++; if(size_con <= 3) {return -1;} size_con -= 3; \
|
||||
uint16_t _value_size; memcpy(&_value_size, iterator, sizeof(_value_size)); _value_size = ntohs(_value_size);\
|
||||
if(size_con < _value_size) { return -1; } size_con -= _value_size; \
|
||||
if ( !(header.header_value = calloc(sizeof(uint8_t), _value_size)) ); \
|
||||
if ( !(header.header_value = calloc(sizeof(uint8_t), _value_size)) ) \
|
||||
LOGGER_ERROR("Allocation failed! Program might misbehave!"); \
|
||||
header.size = _value_size; \
|
||||
memcpy(header.header_value, iterator + 2, _value_size);\
|
||||
|
@ -538,6 +537,233 @@ GENERIC_SETTER_DEFINITION ( info )
|
|||
GENERIC_SETTER_DEFINITION ( callid )
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct _Timer {
|
||||
void *(*func)(void *);
|
||||
void *func_args;
|
||||
uint64_t timeout;
|
||||
size_t idx;
|
||||
|
||||
} Timer;
|
||||
|
||||
typedef struct _TimerHandler {
|
||||
Timer **timers;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
size_t max_capacity;
|
||||
size_t size;
|
||||
uint64_t resolution;
|
||||
|
||||
_Bool running;
|
||||
|
||||
} TimerHandler;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Allocate timer in array
|
||||
*
|
||||
* @param timers_container Handler
|
||||
* @param func Function to be executed
|
||||
* @param arg Its args
|
||||
* @param timeout Timeout in ms
|
||||
* @return int
|
||||
*/
|
||||
int timer_alloc ( TimerHandler *timers_container, void *(func)(void *), void *arg, unsigned timeout)
|
||||
{
|
||||
pthread_mutex_lock(&timers_container->mutex);
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i < timers_container->max_capacity && timers_container->timers[i]; i ++);
|
||||
|
||||
if (i == timers_container->max_capacity) {
|
||||
LOGGER_WARNING("Maximum capacity reached!");
|
||||
pthread_mutex_unlock(&timers_container->mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Timer *timer = timers_container->timers[i] = calloc(sizeof(Timer), 1);
|
||||
|
||||
if (timer == NULL) {
|
||||
LOGGER_ERROR("Failed to allocate timer!");
|
||||
pthread_mutex_unlock(&timers_container->mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
timers_container->size ++;
|
||||
|
||||
timer->func = func;
|
||||
timer->func_args = arg;
|
||||
timer->timeout = timeout + current_time_monotonic(); /* In ms */
|
||||
timer->idx = i;
|
||||
|
||||
/* reorder */
|
||||
if (i) {
|
||||
int j = i - 1;
|
||||
|
||||
for (; j >= 0 && timeout < timers_container->timers[j]->timeout; j--) {
|
||||
Timer *tmp = timers_container->timers[j];
|
||||
timers_container->timers[j] = timer;
|
||||
timers_container->timers[j + 1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&timers_container->mutex);
|
||||
|
||||
LOGGER_DEBUG("Allocated timer index: %d timeout: %d, current size: %d", i, timeout, timers_container->size);
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove timer from array
|
||||
*
|
||||
* @param timers_container handler
|
||||
* @param idx index
|
||||
* @return int
|
||||
*/
|
||||
int timer_release ( TimerHandler *timers_container, int idx )
|
||||
{
|
||||
int rc = pthread_mutex_trylock(&timers_container->mutex);
|
||||
|
||||
Timer **timed_events = timers_container->timers;
|
||||
|
||||
if (!timed_events[idx]) {
|
||||
LOGGER_WARNING("No event under index: %d", idx);
|
||||
|
||||
if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(timed_events[idx]);
|
||||
|
||||
timed_events[idx] = NULL;
|
||||
|
||||
int i = idx + 1;
|
||||
|
||||
for (; i < timers_container->max_capacity && timed_events[i]; i ++) {
|
||||
timed_events[i - 1] = timed_events[i];
|
||||
timed_events[i] = NULL;
|
||||
}
|
||||
|
||||
timers_container->size--;
|
||||
|
||||
LOGGER_DEBUG("Popped index: %d, current size: %d ", idx, timers_container->size);
|
||||
|
||||
if ( rc != EBUSY ) pthread_mutex_unlock(&timers_container->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main poll for timer execution
|
||||
*
|
||||
* @param arg ...
|
||||
* @return void*
|
||||
*/
|
||||
void *timer_poll( void *arg )
|
||||
{
|
||||
TimerHandler *handler = arg;
|
||||
|
||||
while ( handler->running ) {
|
||||
|
||||
pthread_mutex_lock(&handler->mutex);
|
||||
|
||||
if ( handler->running ) {
|
||||
|
||||
uint64_t time = current_time_monotonic();
|
||||
|
||||
while ( handler->timers[0] && handler->timers[0]->timeout < time ) {
|
||||
|
||||
pthread_t _tid;
|
||||
|
||||
if ( 0 != pthread_create(&_tid, NULL, handler->timers[0]->func, handler->timers[0]->func_args) ||
|
||||
0 != pthread_detach(_tid) )
|
||||
LOGGER_ERROR("Failed to execute timer at: %d!", handler->timers[0]->timeout);
|
||||
|
||||
else LOGGER_DEBUG("Exectued timer assigned at: %d", handler->timers[0]->timeout);
|
||||
|
||||
timer_release(handler, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&handler->mutex);
|
||||
|
||||
usleep(handler->resolution);
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start timer poll and return handler
|
||||
*
|
||||
* @param max_capacity capacity
|
||||
* @param resolution ...
|
||||
* @return TimerHandler*
|
||||
*/
|
||||
TimerHandler *timer_init_session (int max_capacity, int resolution)
|
||||
{
|
||||
TimerHandler *handler = calloc(1, sizeof(TimerHandler));
|
||||
|
||||
if (handler == NULL) {
|
||||
LOGGER_ERROR("Failed to allocate memory, program might misbehave!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handler->timers = calloc(max_capacity, sizeof(Timer *));
|
||||
|
||||
if (handler->timers == NULL) {
|
||||
LOGGER_ERROR("Failed to allocate %d timed events!", max_capacity);
|
||||
free(handler);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handler->max_capacity = max_capacity;
|
||||
handler->running = 1;
|
||||
handler->resolution = resolution;
|
||||
|
||||
pthread_mutex_init(&handler->mutex, NULL);
|
||||
|
||||
|
||||
pthread_t _tid;
|
||||
|
||||
if ( 0 != pthread_create(&_tid, NULL, timer_poll, handler) || 0 != pthread_detach(_tid) ) {
|
||||
LOGGER_ERROR("Failed to start timer poll thread!");
|
||||
free(handler->timers);
|
||||
free(handler);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Terminate timer session
|
||||
*
|
||||
* @param handler The timer handler
|
||||
* @return void
|
||||
*/
|
||||
void timer_terminate_session(TimerHandler *handler)
|
||||
{
|
||||
pthread_mutex_lock(&handler->mutex);
|
||||
|
||||
handler->running = 0;
|
||||
|
||||
pthread_mutex_unlock(&handler->mutex);
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i < handler->max_capacity; i ++)
|
||||
free(handler->timers[i]);
|
||||
|
||||
free(handler->timers);
|
||||
|
||||
pthread_mutex_destroy( &handler->mutex );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate _random_ alphanumerical string.
|
||||
*
|
||||
|
@ -731,7 +957,11 @@ MSICall *find_call ( MSISession *session, uint8_t *call_id )
|
|||
|
||||
for (; i < session->max_calls; i ++ )
|
||||
if ( session->calls[i] && memcmp(session->calls[i]->id, call_id, CALL_ID_LEN) == 0 ) {
|
||||
LOGGER_DEBUG("Found call id: %s", session->calls[i]->id);
|
||||
LOGGER_SCOPE(
|
||||
char tmp[CALL_ID_LEN + 1] = {'\0'};
|
||||
memcpy(tmp, session->calls[i]->id, CALL_ID_LEN);
|
||||
LOGGER_DEBUG("Found call id: %s", tmp);
|
||||
);
|
||||
return session->calls[i];
|
||||
}
|
||||
|
||||
|
@ -883,8 +1113,8 @@ int terminate_call ( MSISession *session, MSICall *call )
|
|||
* NOTE: This has to be done before possibly
|
||||
* locking the mutex the second time
|
||||
*/
|
||||
event.timer_release ( call->request_timer_id );
|
||||
event.timer_release ( call->ringing_timer_id );
|
||||
timer_release ( session->timer_handler, call->request_timer_id );
|
||||
timer_release ( session->timer_handler, call->ringing_timer_id );
|
||||
|
||||
/* Get a handle */
|
||||
pthread_mutex_lock ( &call->mutex );
|
||||
|
@ -1055,10 +1285,6 @@ int handle_recv_reject ( MSISession *session, MSICall *call, MSIMessage *msg )
|
|||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
invoke_callback(call->call_idx, MSI_OnReject);
|
||||
/*
|
||||
event.timer_release ( session->call->request_timer_id );
|
||||
session->call->request_timer_id = event.timer_alloc ( handle_timeout, session, m_deftout );
|
||||
*/
|
||||
|
||||
terminate_call(session, call);
|
||||
return 1;
|
||||
|
@ -1123,7 +1349,7 @@ int handle_recv_ringing ( MSISession *session, MSICall *call, MSIMessage *msg )
|
|||
|
||||
LOGGER_DEBUG("Session: %p Handling 'ringing' on call: %s", session, call->id );
|
||||
|
||||
call->ringing_timer_id = event.timer_alloc ( handle_timeout, call, call->ringing_tout_ms );
|
||||
call->ringing_timer_id = timer_alloc ( session->timer_handler, handle_timeout, call, call->ringing_tout_ms );
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
|
@ -1150,7 +1376,7 @@ int handle_recv_starting ( MSISession *session, MSICall *call, MSIMessage *msg )
|
|||
flush_peer_type ( call, msg, 0 );
|
||||
|
||||
|
||||
event.timer_release ( call->ringing_timer_id );
|
||||
timer_release ( session->timer_handler, call->ringing_timer_id );
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
invoke_callback(call->call_idx, MSI_OnStarting);
|
||||
|
@ -1168,7 +1394,7 @@ int handle_recv_ending ( MSISession *session, MSICall *call, MSIMessage *msg )
|
|||
LOGGER_DEBUG("Session: %p Handling 'ending' on call: %s", session, call->id );
|
||||
|
||||
/* Stop timer */
|
||||
event.timer_release ( call->request_timer_id );
|
||||
timer_release ( session->timer_handler, call->request_timer_id );
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
|
@ -1246,89 +1472,88 @@ void msi_handle_packet ( Messenger *messenger, int source, const uint8_t *data,
|
|||
/* Unused */
|
||||
(void)messenger;
|
||||
|
||||
MSISession *_session = object;
|
||||
MSIMessage *_msg;
|
||||
MSISession *session = object;
|
||||
MSIMessage *msg;
|
||||
|
||||
if ( !length ) {
|
||||
LOGGER_WARNING("Lenght param negative");
|
||||
return;
|
||||
}
|
||||
|
||||
_msg = parse_message ( data, length );
|
||||
msg = parse_message ( data, length );
|
||||
|
||||
if ( !_msg ) {
|
||||
if ( !msg ) {
|
||||
LOGGER_WARNING("Error parsing message");
|
||||
return;
|
||||
} else {
|
||||
LOGGER_DEBUG("Successfully parsed message");
|
||||
}
|
||||
|
||||
_msg->friend_id = source;
|
||||
msg->friend_id = source;
|
||||
|
||||
|
||||
/* Find what call */
|
||||
MSICall *_call = _msg->callid.header_value ? find_call(_session, _msg->callid.header_value ) : NULL;
|
||||
MSICall *call = msg->callid.header_value ? find_call(session, msg->callid.header_value ) : NULL;
|
||||
|
||||
/* Now handle message */
|
||||
|
||||
if ( _msg->request.header_value ) { /* Handle request */
|
||||
if ( msg->request.header_value ) { /* Handle request */
|
||||
|
||||
if ( _msg->response.size > 32 ) {
|
||||
if ( msg->response.size > 32 ) {
|
||||
LOGGER_WARNING("Header size too big");
|
||||
goto free_end;
|
||||
}
|
||||
|
||||
uint8_t _request_value[32];
|
||||
|
||||
memcpy(_request_value, _msg->request.header_value, _msg->request.size);
|
||||
_request_value[_msg->request.size] = '\0';
|
||||
memcpy(_request_value, msg->request.header_value, msg->request.size);
|
||||
_request_value[msg->request.size] = '\0';
|
||||
|
||||
if ( same ( _request_value, stringify_request ( invite ) ) ) {
|
||||
handle_recv_invite ( _session, _call, _msg );
|
||||
handle_recv_invite ( session, call, msg );
|
||||
|
||||
} else if ( same ( _request_value, stringify_request ( start ) ) ) {
|
||||
handle_recv_start ( _session, _call, _msg );
|
||||
handle_recv_start ( session, call, msg );
|
||||
|
||||
} else if ( same ( _request_value, stringify_request ( cancel ) ) ) {
|
||||
handle_recv_cancel ( _session, _call, _msg );
|
||||
handle_recv_cancel ( session, call, msg );
|
||||
|
||||
} else if ( same ( _request_value, stringify_request ( reject ) ) ) {
|
||||
handle_recv_reject ( _session, _call, _msg );
|
||||
handle_recv_reject ( session, call, msg );
|
||||
|
||||
} else if ( same ( _request_value, stringify_request ( end ) ) ) {
|
||||
handle_recv_end ( _session, _call, _msg );
|
||||
handle_recv_end ( session, call, msg );
|
||||
} else {
|
||||
LOGGER_WARNING("Uknown request");
|
||||
goto free_end;
|
||||
}
|
||||
|
||||
} else if ( _msg->response.header_value ) { /* Handle response */
|
||||
} else if ( msg->response.header_value ) { /* Handle response */
|
||||
|
||||
if ( _msg->response.size > 32 ) {
|
||||
if ( msg->response.size > 32 ) {
|
||||
LOGGER_WARNING("Header size too big");
|
||||
goto free_end;
|
||||
}
|
||||
|
||||
/* Got response so cancel timer */
|
||||
if ( _call )
|
||||
event.timer_release ( _call->request_timer_id );
|
||||
if ( call ) timer_release ( session->timer_handler, call->request_timer_id );
|
||||
|
||||
uint8_t _response_value[32];
|
||||
|
||||
memcpy(_response_value, _msg->response.header_value, _msg->response.size);
|
||||
_response_value[_msg->response.size] = '\0';
|
||||
memcpy(_response_value, msg->response.header_value, msg->response.size);
|
||||
_response_value[msg->response.size] = '\0';
|
||||
|
||||
if ( same ( _response_value, stringify_response ( ringing ) ) ) {
|
||||
handle_recv_ringing ( _session, _call, _msg );
|
||||
handle_recv_ringing ( session, call, msg );
|
||||
|
||||
} else if ( same ( _response_value, stringify_response ( starting ) ) ) {
|
||||
handle_recv_starting ( _session, _call, _msg );
|
||||
handle_recv_starting ( session, call, msg );
|
||||
|
||||
} else if ( same ( _response_value, stringify_response ( ending ) ) ) {
|
||||
handle_recv_ending ( _session, _call, _msg );
|
||||
handle_recv_ending ( session, call, msg );
|
||||
|
||||
} else if ( same ( _response_value, stringify_response ( error ) ) ) {
|
||||
handle_recv_error ( _session, _call, _msg );
|
||||
handle_recv_error ( session, call, msg );
|
||||
|
||||
} else {
|
||||
LOGGER_WARNING("Uknown response");
|
||||
|
@ -1340,7 +1565,7 @@ void msi_handle_packet ( Messenger *messenger, int source, const uint8_t *data,
|
|||
}
|
||||
|
||||
free_end:
|
||||
free_message ( _msg );
|
||||
free_message ( msg );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1373,7 +1598,12 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if ( !max_calls) return NULL;
|
||||
TimerHandler *handler = timer_init_session(max_calls * 10, 10000);
|
||||
|
||||
if ( !max_calls || !handler ) {
|
||||
LOGGER_WARNING("Invalid max call treshold or timer handler initialization failed!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MSISession *_retu = calloc ( sizeof ( MSISession ), 1 );
|
||||
|
||||
|
@ -1384,6 +1614,7 @@ MSISession *msi_init_session ( Messenger *messenger, int32_t max_calls )
|
|||
|
||||
_retu->messenger_handle = messenger;
|
||||
_retu->agent_handler = NULL;
|
||||
_retu->timer_handler = handler;
|
||||
|
||||
if (!(_retu->calls = calloc( sizeof (MSICall *), max_calls ))) {
|
||||
LOGGER_ERROR("Allocation failed! Program might misbehave!");
|
||||
|
@ -1440,6 +1671,7 @@ int msi_terminate_session ( MSISession *session )
|
|||
msi_cancel ( session, idx, session->calls[idx]->peers [_it], "MSI session terminated!" );
|
||||
}
|
||||
|
||||
timer_terminate_session(session->timer_handler);
|
||||
|
||||
pthread_mutex_destroy(&session->mutex);
|
||||
|
||||
|
@ -1495,7 +1727,7 @@ int msi_invite ( MSISession *session, int32_t *call_index, MSICallType call_type
|
|||
|
||||
_call->state = call_inviting;
|
||||
|
||||
_call->request_timer_id = event.timer_alloc ( handle_timeout, _call, m_deftout );
|
||||
_call->request_timer_id = timer_alloc ( session->timer_handler, handle_timeout, _call, m_deftout );
|
||||
|
||||
LOGGER_DEBUG("Invite sent");
|
||||
|
||||
|
@ -1543,8 +1775,8 @@ int msi_hangup ( MSISession *session, int32_t call_index )
|
|||
|
||||
free_message ( _msg_end );
|
||||
|
||||
session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index],
|
||||
m_deftout );
|
||||
session->calls[call_index]->request_timer_id =
|
||||
timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
return 0;
|
||||
|
@ -1620,7 +1852,7 @@ int msi_cancel ( MSISession *session, int32_t call_index, uint32_t peer, const c
|
|||
free_message ( _msg_cancel );
|
||||
|
||||
/*session->calls[call_index]->state = call_hanged_up;
|
||||
session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index], m_deftout );*/
|
||||
session->calls[call_index]->request_timer_id = timer_alloc ( handle_timeout, session->calls[call_index], m_deftout );*/
|
||||
terminate_call ( session, session->calls[call_index] );
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
|
@ -1656,8 +1888,8 @@ int msi_reject ( MSISession *session, int32_t call_index, const uint8_t *reason
|
|||
|
||||
session->calls[call_index]->state = call_hanged_up;
|
||||
|
||||
session->calls[call_index]->request_timer_id = event.timer_alloc ( handle_timeout, session->calls[call_index],
|
||||
m_deftout );
|
||||
session->calls[call_index]->request_timer_id =
|
||||
timer_alloc ( session->timer_handler, handle_timeout, session->calls[call_index], m_deftout );
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
return 0;
|
||||
|
|
|
@ -105,6 +105,8 @@ typedef struct _MSISession {
|
|||
uint32_t call_timeout; /* Time of the timeout for some action to end; 0 if infinite */
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
void *timer_handler;
|
||||
} MSISession;
|
||||
|
||||
|
||||
|
|
105
toxav/toxav.c
105
toxav/toxav.c
|
@ -66,6 +66,8 @@ typedef struct _CallSpecific {
|
|||
uint32_t frame_limit; /* largest address written to in frame_buf for current input frame*/
|
||||
uint8_t frame_id, frame_outid; /* id of input and output video frame */
|
||||
void *frame_buf; /* buffer for split video payloads */
|
||||
|
||||
_Bool call_active;
|
||||
} CallSpecific;
|
||||
|
||||
|
||||
|
@ -296,8 +298,9 @@ int toxav_stop_call ( ToxAv *av, int32_t call_index )
|
|||
*/
|
||||
int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettings *codec_settings, int support_video )
|
||||
{
|
||||
if ( !av->msi_session || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) {
|
||||
LOGGER_ERROR("Error while starting audio RTP session: invalid call!\n");
|
||||
if ( !av->msi_session || cii(call_index, av->msi_session) ||
|
||||
!av->msi_session->calls[call_index] || av->calls[call_index].call_active) {
|
||||
LOGGER_ERROR("Error while starting RTP session: invalid call!\n");
|
||||
return ErrorInternal;
|
||||
}
|
||||
|
||||
|
@ -320,6 +323,8 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
|
|||
|
||||
if ( !call->crtps[video_index] ) {
|
||||
LOGGER_ERROR("Error while starting video RTP session!\n");
|
||||
|
||||
rtp_terminate_session(call->crtps[audio_index], av->messenger);
|
||||
return ErrorStartingVideoRtp;
|
||||
}
|
||||
|
||||
|
@ -330,23 +335,40 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
|
|||
call->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1);
|
||||
|
||||
if (!call->frame_buf) {
|
||||
rtp_terminate_session(call->crtps[audio_index], av->messenger);
|
||||
rtp_terminate_session(call->crtps[video_index], av->messenger);
|
||||
LOGGER_WARNING("Frame buffer allocation failed!");
|
||||
return ErrorInternal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) return ErrorInternal;
|
||||
if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) {
|
||||
rtp_terminate_session(call->crtps[audio_index], av->messenger);
|
||||
rtp_terminate_session(call->crtps[video_index], av->messenger);
|
||||
free(call->frame_buf);
|
||||
LOGGER_WARNING("Jitter buffer creaton failed!");
|
||||
return ErrorInternal;
|
||||
}
|
||||
|
||||
call->cs = codec_init_session(codec_settings->audio_bitrate,
|
||||
codec_settings->audio_frame_duration,
|
||||
codec_settings->audio_sample_rate,
|
||||
codec_settings->audio_channels,
|
||||
codec_settings->audio_VAD_tolerance,
|
||||
codec_settings->video_width,
|
||||
codec_settings->video_height,
|
||||
codec_settings->video_bitrate);
|
||||
if ( (call->cs = codec_init_session(codec_settings->audio_bitrate,
|
||||
codec_settings->audio_frame_duration,
|
||||
codec_settings->audio_sample_rate,
|
||||
codec_settings->audio_channels,
|
||||
codec_settings->audio_VAD_tolerance,
|
||||
codec_settings->video_width,
|
||||
codec_settings->video_height,
|
||||
codec_settings->video_bitrate) )) {
|
||||
call->call_active = 1;
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
return call->cs ? ErrorNone : ErrorInternal;
|
||||
rtp_terminate_session(call->crtps[audio_index], av->messenger);
|
||||
rtp_terminate_session(call->crtps[video_index], av->messenger);
|
||||
free(call->frame_buf);
|
||||
terminate_queue(call->j_buf);
|
||||
|
||||
return ErrorInternal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -359,22 +381,24 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
|
|||
*/
|
||||
int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
|
||||
{
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
|
||||
call->call_active = 0;
|
||||
|
||||
if ( call->crtps[audio_index] && -1 == rtp_terminate_session(call->crtps[audio_index], av->messenger) ) {
|
||||
LOGGER_ERROR("Error while terminating audio RTP session!\n");
|
||||
return ErrorTerminatingAudioRtp;
|
||||
}
|
||||
/*return ErrorTerminatingAudioRtp;*/
|
||||
} else call->crtps[audio_index] = NULL;
|
||||
|
||||
if ( call->crtps[video_index] && -1 == rtp_terminate_session(call->crtps[video_index], av->messenger) ) {
|
||||
LOGGER_ERROR("Error while terminating video RTP session!\n");
|
||||
return ErrorTerminatingVideoRtp;
|
||||
}
|
||||
|
||||
call->crtps[audio_index] = NULL;
|
||||
call->crtps[video_index] = NULL;
|
||||
/*return ErrorTerminatingVideoRtp;*/
|
||||
} else call->crtps[video_index] = NULL;
|
||||
|
||||
if ( call->j_buf ) {
|
||||
terminate_queue(call->j_buf);
|
||||
|
@ -388,6 +412,7 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
|
|||
LOGGER_DEBUG("Terminated codec session");
|
||||
} else LOGGER_DEBUG("No codec session");
|
||||
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
|
@ -406,8 +431,6 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index )
|
|||
inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, const uint8_t *payload,
|
||||
unsigned int length )
|
||||
{
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
|
||||
#define send(data, len) rtp_send_msg(av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, data, len)
|
||||
|
||||
if (av->calls[call_index].crtps[type - TypeAudio]) {
|
||||
|
@ -465,8 +488,6 @@ inline__ int toxav_recv_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallTy
|
|||
{
|
||||
if ( !dest ) return ErrorInternal;
|
||||
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
|
||||
if ( !call->crtps[type - TypeAudio] ) return ErrorNoRtpSession;
|
||||
|
@ -518,7 +539,11 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out
|
|||
{
|
||||
if ( !output ) return ErrorInternal;
|
||||
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
|
||||
uint8_t packet [RTP_PAYLOAD_SIZE];
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
|
@ -586,7 +611,11 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out
|
|||
*/
|
||||
inline__ int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, int frame_size)
|
||||
{
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
|
||||
return toxav_send_rtp_payload(av, call_index, TypeVideo, frame, frame_size);
|
||||
}
|
||||
|
@ -604,7 +633,11 @@ inline__ int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *fr
|
|||
*/
|
||||
inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input)
|
||||
{
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
|
||||
|
@ -649,7 +682,11 @@ inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, i
|
|||
{
|
||||
if ( !dest ) return ErrorInternal;
|
||||
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
|
||||
|
@ -690,7 +727,11 @@ inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, i
|
|||
*/
|
||||
inline__ int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *frame, int frame_size)
|
||||
{
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
|
||||
return toxav_send_rtp_payload(av, call_index, TypeAudio, frame, frame_size);
|
||||
}
|
||||
|
@ -710,7 +751,11 @@ inline__ int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *fr
|
|||
inline__ int toxav_prepare_audio_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max,
|
||||
const int16_t *frame, int frame_size)
|
||||
{
|
||||
if (cii(call_index, av->msi_session)) return ErrorNoCall;
|
||||
if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) {
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
|
||||
int32_t rc = opus_encode(av->calls[call_index].cs->audio_encoder, frame, frame_size, dest, dest_max);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user