mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge branch 'split-video' of https://github.com/notsecure/toxcore
This commit is contained in:
commit
909db02941
|
@ -138,6 +138,15 @@ void callback_requ_timeout ( int32_t call_index, void *_arg )
|
|||
{
|
||||
ck_assert_msg(0, "No answer!");
|
||||
}
|
||||
|
||||
static void callback_audio(ToxAv *av, int32_t call_index, int16_t *data, int length)
|
||||
{
|
||||
}
|
||||
|
||||
static void callback_video(ToxAv *av, int32_t call_index, vpx_image_t *img)
|
||||
{
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
/* Alice calls bob and the call starts.
|
||||
|
@ -222,6 +231,10 @@ START_TEST(test_AV_flows)
|
|||
toxav_register_callstate_callback(callback_recv_error, av_OnError, &status_control);
|
||||
toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, &status_control);
|
||||
|
||||
toxav_register_audio_recv_callback(status_control.Alice.av, callback_audio);
|
||||
toxav_register_video_recv_callback(status_control.Alice.av, callback_video);
|
||||
toxav_register_audio_recv_callback(status_control.Bob.av, callback_audio);
|
||||
toxav_register_video_recv_callback(status_control.Bob.av, callback_video);
|
||||
|
||||
const int frame_size = (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000);
|
||||
int16_t sample_payload[frame_size];
|
||||
|
@ -267,21 +280,22 @@ START_TEST(test_AV_flows)
|
|||
toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size);
|
||||
|
||||
/* Both receive */
|
||||
int16_t storage[frame_size];
|
||||
/*int16_t storage[frame_size];
|
||||
int recved;
|
||||
|
||||
/* Payload from Bob */
|
||||
recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, frame_size, storage);
|
||||
|
||||
/*recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, frame_size, storage);
|
||||
|
||||
if ( recved ) {
|
||||
/*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/
|
||||
//ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");
|
||||
}
|
||||
|
||||
recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, frame_size, storage);
|
||||
|
||||
if ( recved ) {
|
||||
/*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/
|
||||
}
|
||||
//ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");
|
||||
}*/
|
||||
|
||||
if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */
|
||||
step++; /* This terminates the loop */
|
||||
|
@ -326,11 +340,11 @@ START_TEST(test_AV_flows)
|
|||
int recved;
|
||||
|
||||
/* Payload from Bob */
|
||||
recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, frame_size, storage);
|
||||
/*recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, frame_size, storage);
|
||||
|
||||
if ( recved ) {
|
||||
/*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/
|
||||
}
|
||||
//ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");
|
||||
}*/
|
||||
|
||||
/* Video payload */
|
||||
// toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage);
|
||||
|
@ -346,11 +360,11 @@ START_TEST(test_AV_flows)
|
|||
|
||||
|
||||
/* Payload from Alice */
|
||||
recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, frame_size, storage);
|
||||
/*recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, frame_size, storage);
|
||||
|
||||
if ( recved ) {
|
||||
/*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/
|
||||
}
|
||||
//ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");
|
||||
}*/
|
||||
|
||||
if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */
|
||||
step++; /* This terminates the loop */
|
||||
|
@ -397,11 +411,11 @@ START_TEST(test_AV_flows)
|
|||
int recved;
|
||||
|
||||
/* Payload from Bob */
|
||||
recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, frame_size, storage);
|
||||
/*recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, frame_size, storage);
|
||||
|
||||
if ( recved ) {
|
||||
/*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/
|
||||
}
|
||||
//ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");
|
||||
}*/
|
||||
|
||||
/* Video payload */
|
||||
// toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage);
|
||||
|
@ -417,11 +431,11 @@ START_TEST(test_AV_flows)
|
|||
|
||||
|
||||
/* Payload from Alice */
|
||||
recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, frame_size, storage);
|
||||
/*recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, frame_size, storage);
|
||||
|
||||
if ( recved ) {
|
||||
/*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/
|
||||
}
|
||||
ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");
|
||||
}*/
|
||||
|
||||
/* Video payload */
|
||||
// toxav_recv_video(status_control.Bob.av, status_control.Bob.call_index, &video_storage);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define c_sleep(x) usleep(1000*x)
|
||||
#endif
|
||||
|
||||
pthread_mutex_t muhmutex;
|
||||
|
||||
typedef enum _CallStatus {
|
||||
none,
|
||||
|
@ -124,6 +125,14 @@ void callback_requ_timeout ( int32_t call_index, void *_arg )
|
|||
{
|
||||
ck_assert_msg(0, "No answer!");
|
||||
}
|
||||
|
||||
static void callback_audio(ToxAv *av, int32_t call_index, int16_t *data, int length)
|
||||
{
|
||||
}
|
||||
|
||||
static void callback_video(ToxAv *av, int32_t call_index, vpx_image_t *img)
|
||||
{
|
||||
}
|
||||
/*************************************************************************************************/
|
||||
|
||||
|
||||
|
@ -142,6 +151,11 @@ void *in_thread_call (void *arg)
|
|||
|
||||
uint8_t prepared_payload[RTP_PAYLOAD_SIZE];
|
||||
|
||||
toxav_register_audio_recv_callback(this_call->Caller.av, callback_audio);
|
||||
toxav_register_video_recv_callback(this_call->Caller.av, callback_video);
|
||||
toxav_register_audio_recv_callback(this_call->Callee.av, callback_audio);
|
||||
toxav_register_video_recv_callback(this_call->Callee.av, callback_video);
|
||||
|
||||
|
||||
/* NOTE: CALLEE WILL ALWAHYS NEED CALL_IDX == 0 */
|
||||
while (running) {
|
||||
|
@ -192,26 +206,28 @@ void *in_thread_call (void *arg)
|
|||
int recved;
|
||||
|
||||
/* Payload from CALLER */
|
||||
recved = toxav_recv_audio(this_call->Callee.av, 0, frame_size, storage);
|
||||
/*recved = toxav_recv_audio(this_call->Callee.av, 0, frame_size, storage);
|
||||
|
||||
if ( recved ) {
|
||||
/*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from CALLER is invalid");*/
|
||||
}
|
||||
//ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from CALLER is invalid");
|
||||
}*/
|
||||
|
||||
/* Payload from CALLEE */
|
||||
recved = toxav_recv_audio(this_call->Caller.av, call_idx, frame_size, storage);
|
||||
/*recved = toxav_recv_audio(this_call->Caller.av, call_idx, frame_size, storage);
|
||||
|
||||
if ( recved ) {
|
||||
/*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from CALLEE is invalid");*/
|
||||
}
|
||||
//ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from CALLEE is invalid");
|
||||
}*/
|
||||
|
||||
c_sleep(20);
|
||||
}
|
||||
|
||||
step++; /* This terminates the loop */
|
||||
|
||||
pthread_mutex_lock(&muhmutex);
|
||||
toxav_kill_transmission(this_call->Callee.av, 0);
|
||||
toxav_kill_transmission(this_call->Caller.av, call_idx);
|
||||
pthread_mutex_unlock(&muhmutex);
|
||||
|
||||
/* Call over CALLER hangs up */
|
||||
toxav_hangup(this_call->Caller.av, call_idx);
|
||||
|
@ -335,6 +351,8 @@ START_TEST(test_AV_three_calls)
|
|||
toxav_register_callstate_callback(callback_requ_timeout, av_OnRequestTimeout, &status_control);
|
||||
|
||||
|
||||
pthread_mutex_init(&muhmutex, NULL);
|
||||
|
||||
|
||||
for ( i = 0; i < 3; i++ )
|
||||
pthread_create(&status_control.calls[i].tid, NULL, in_thread_call, &status_control.calls[i]);
|
||||
|
@ -350,11 +368,15 @@ START_TEST(test_AV_three_calls)
|
|||
status_control.calls[1].Callee.status != Ended && status_control.calls[1].Caller.status != Ended &&
|
||||
status_control.calls[2].Callee.status != Ended && status_control.calls[2].Caller.status != Ended
|
||||
) {
|
||||
pthread_mutex_lock(&muhmutex);
|
||||
|
||||
tox_do(bootstrap_node);
|
||||
tox_do(caller);
|
||||
tox_do(callees[0]);
|
||||
tox_do(callees[1]);
|
||||
tox_do(callees[2]);
|
||||
|
||||
pthread_mutex_unlock(&muhmutex);
|
||||
c_sleep(20);
|
||||
}
|
||||
|
||||
|
@ -403,4 +425,4 @@ int main(int argc, char *argv[])
|
|||
// test_AV_three_calls();
|
||||
//
|
||||
// return 0;
|
||||
}
|
||||
}
|
||||
|
|
132
toxav/rtp.c
132
toxav/rtp.c
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "rtp.h"
|
||||
#include <stdlib.h>
|
||||
void toxav_handle_packet(RTPSession *_session, RTPMessage *_msg);
|
||||
|
||||
#define size_32 4
|
||||
|
||||
|
@ -372,11 +373,6 @@ int rtp_handle_packet ( void *object, const uint8_t *data, uint32_t length )
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ( _session->queue_limit <= _session->queue_size ) {
|
||||
LOGGER_WARNING("Queue limit reached!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_msg = msg_parse ( data + 1, length - 1 );
|
||||
|
||||
if ( !_msg ) {
|
||||
|
@ -390,18 +386,7 @@ int rtp_handle_packet ( void *object, const uint8_t *data, uint32_t length )
|
|||
_session->timestamp = _msg->header->timestamp;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&_session->mutex);
|
||||
|
||||
if ( _session->last_msg ) {
|
||||
_session->last_msg->next = _msg;
|
||||
_session->last_msg = _msg;
|
||||
} else {
|
||||
_session->last_msg = _session->oldest_msg = _msg;
|
||||
}
|
||||
|
||||
_session->queue_size++;
|
||||
|
||||
pthread_mutex_unlock(&_session->mutex);
|
||||
toxav_handle_packet(_session, _msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -467,105 +452,6 @@ RTPMessage *rtp_new_message ( RTPSession *session, const uint8_t *data, uint32_t
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Release all messages held by session.
|
||||
*
|
||||
* @param session The session.
|
||||
* @return int
|
||||
* @retval -1 Error occurred.
|
||||
* @retval 0 Success.
|
||||
*/
|
||||
int rtp_release_session_recv ( RTPSession *session )
|
||||
{
|
||||
if ( !session ) {
|
||||
LOGGER_WARNING("No session!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
RTPMessage *_tmp, * _it;
|
||||
|
||||
pthread_mutex_lock(&session->mutex);
|
||||
|
||||
for ( _it = session->oldest_msg; _it; _it = _tmp ) {
|
||||
_tmp = _it->next;
|
||||
rtp_free_msg( session, _it);
|
||||
}
|
||||
|
||||
session->last_msg = session->oldest_msg = NULL;
|
||||
session->queue_size = 0;
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Call this to change queue limit
|
||||
*
|
||||
* @param session The session
|
||||
* @param limit new limit
|
||||
* @return void
|
||||
*/
|
||||
void rtp_queue_adjust_limit(RTPSession *session, uint64_t limit)
|
||||
{
|
||||
pthread_mutex_lock(&session->mutex);
|
||||
|
||||
RTPMessage *_tmp, * _it = session->oldest_msg;
|
||||
|
||||
for ( ; session->queue_size > limit; _it = _tmp ) {
|
||||
_tmp = _it->next;
|
||||
rtp_free_msg( session, _it);
|
||||
session->queue_size --;
|
||||
}
|
||||
|
||||
session->oldest_msg = _it;
|
||||
session->queue_limit = limit;
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets oldest message in the list.
|
||||
*
|
||||
* @param session Where the list is.
|
||||
* @return RTPMessage* The message. You _must_ call rtp_msg_free() to free it.
|
||||
* @retval NULL No messages in the list, or no list.
|
||||
*/
|
||||
RTPMessage *rtp_recv_msg ( RTPSession *session )
|
||||
{
|
||||
if ( !session ) {
|
||||
LOGGER_WARNING("No session!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&session->mutex);
|
||||
|
||||
if ( session->queue_size == 0 ) {
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
RTPMessage *_retu = session->oldest_msg;
|
||||
|
||||
/*if (_retu)*/
|
||||
session->oldest_msg = _retu->next;
|
||||
|
||||
if ( !session->oldest_msg )
|
||||
session->last_msg = NULL;
|
||||
|
||||
session->queue_size --;
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
|
||||
return _retu;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sends data to _RTPSession::dest
|
||||
*
|
||||
|
@ -627,7 +513,6 @@ void rtp_free_msg ( RTPSession *session, RTPMessage *msg )
|
|||
free ( msg );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Must be called before calling any other rtp function. It's used
|
||||
* to initialize RTP control session.
|
||||
|
@ -682,11 +567,6 @@ RTPSession *rtp_init_session ( int payload_type, Messenger *messenger, int frien
|
|||
/* Also set payload type as prefix */
|
||||
_retu->prefix = payload_type;
|
||||
|
||||
_retu->oldest_msg = _retu->last_msg = NULL;
|
||||
_retu->queue_limit = 100; /* Default */
|
||||
_retu->queue_size = 0;
|
||||
|
||||
pthread_mutex_init(&_retu->mutex, NULL);
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
@ -709,17 +589,9 @@ void rtp_terminate_session ( RTPSession *session, Messenger *messenger )
|
|||
|
||||
custom_lossy_packet_registerhandler(messenger, session->dest, session->prefix, NULL, NULL);
|
||||
|
||||
rtp_release_session_recv(session);
|
||||
|
||||
pthread_mutex_lock(&session->mutex);
|
||||
|
||||
free ( session->ext_header );
|
||||
free ( session->csrc );
|
||||
|
||||
pthread_mutex_unlock(&session->mutex);
|
||||
|
||||
pthread_mutex_destroy(&session->mutex);
|
||||
|
||||
LOGGER_DEBUG("Terminated RTP session: %p", session);
|
||||
|
||||
/* And finally free session */
|
||||
|
|
10
toxav/rtp.h
10
toxav/rtp.h
|
@ -105,17 +105,12 @@ typedef struct _RTPSession {
|
|||
*/
|
||||
RTPExtHeader *ext_header;
|
||||
|
||||
RTPMessage *oldest_msg;
|
||||
RTPMessage *last_msg; /* tail */
|
||||
|
||||
uint64_t queue_limit;/* Default 100; modify per thy liking */
|
||||
uint64_t queue_size; /* currently holding << messages */
|
||||
|
||||
/* Msg prefix for core to know when recving */
|
||||
uint8_t prefix;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
int dest;
|
||||
int32_t call_index;
|
||||
struct _ToxAv *av;
|
||||
|
||||
} RTPSession;
|
||||
|
||||
|
@ -172,7 +167,6 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat
|
|||
*/
|
||||
void rtp_free_msg ( RTPSession *session, RTPMessage *msg );
|
||||
|
||||
|
||||
/**
|
||||
* @brief Must be called before calling any other rtp function. It's used
|
||||
* to initialize RTP control session.
|
||||
|
|
349
toxav/toxav.c
349
toxav/toxav.c
|
@ -76,6 +76,10 @@ struct _ToxAv {
|
|||
Messenger *messenger;
|
||||
MSISession *msi_session; /** Main msi session */
|
||||
CallSpecific *calls; /** Per-call params */
|
||||
|
||||
void (*audio_callback)(ToxAv *, int32_t, int16_t *, int);
|
||||
void (*video_callback)(ToxAv *, int32_t, vpx_image_t *);
|
||||
|
||||
uint32_t max_calls;
|
||||
};
|
||||
|
||||
|
@ -168,6 +172,28 @@ void toxav_register_callstate_callback ( ToxAVCallback callback, ToxAvCallbackID
|
|||
msi_register_callback((MSICallback)callback, (MSICallbackID) id, userdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register callback for recieving audio data
|
||||
*
|
||||
* @param callback The callback
|
||||
* @return void
|
||||
*/
|
||||
void toxav_register_audio_recv_callback (ToxAv *av, void (*callback)(ToxAv *, int32_t, int16_t *, int))
|
||||
{
|
||||
av->audio_callback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register callback for recieving video data
|
||||
*
|
||||
* @param callback The callback
|
||||
* @return void
|
||||
*/
|
||||
void toxav_register_video_recv_callback (ToxAv *av, void (*callback)(ToxAv *, int32_t, vpx_image_t *))
|
||||
{
|
||||
av->video_callback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call user. Use its friend_id.
|
||||
*
|
||||
|
@ -316,17 +342,21 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin
|
|||
return ErrorInternal;
|
||||
}
|
||||
|
||||
call->crtps[audio_index]->call_index = call_index;
|
||||
call->crtps[audio_index]->av = av;
|
||||
|
||||
if ( support_video ) {
|
||||
call->crtps[video_index] =
|
||||
rtp_init_session(type_video, av->messenger, av->msi_session->calls[call_index]->peers[0]);
|
||||
|
||||
|
||||
if ( !call->crtps[video_index] ) {
|
||||
LOGGER_ERROR("Error while starting video RTP session!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
call->crtps[video_index]->call_index = call_index;
|
||||
call->crtps[video_index]->av = av;
|
||||
|
||||
call->frame_limit = 0;
|
||||
call->frame_id = 0;
|
||||
call->frame_outid = 0;
|
||||
|
@ -474,140 +504,6 @@ inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallTy
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive RTP payload.
|
||||
*
|
||||
* @param av Handler.
|
||||
* @param type Type of the payload.
|
||||
* @param dest Storage.
|
||||
* @return int
|
||||
* @retval ToxAvError On Error.
|
||||
* @retval >=0 Size of received payload.
|
||||
*/
|
||||
inline__ int toxav_recv_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, uint8_t *dest )
|
||||
{
|
||||
if ( !dest ) return ErrorInternal;
|
||||
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
|
||||
if ( !call->crtps[type - TypeAudio] ) return ErrorNoRtpSession;
|
||||
|
||||
RTPMessage *message;
|
||||
|
||||
if ( type == TypeAudio ) {
|
||||
|
||||
do {
|
||||
message = rtp_recv_msg(call->crtps[audio_index]);
|
||||
|
||||
if (message) {
|
||||
/* push the packet into the queue */
|
||||
queue(call->j_buf, message);
|
||||
}
|
||||
} while (message);
|
||||
|
||||
int success = 0;
|
||||
message = dequeue(call->j_buf, &success);
|
||||
|
||||
if ( success == 2) return ErrorAudioPacketLost;
|
||||
} else {
|
||||
message = rtp_recv_msg(call->crtps[video_index]);
|
||||
}
|
||||
|
||||
if ( message ) {
|
||||
memcpy(dest, message->data, message->length);
|
||||
|
||||
int length = message->length;
|
||||
|
||||
rtp_free_msg(NULL, message);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive decoded video packet.
|
||||
*
|
||||
* @param av Handler.
|
||||
* @param output Storage.
|
||||
* @return int
|
||||
* @retval 0 Success.
|
||||
* @retval ToxAvError On Error.
|
||||
*/
|
||||
inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **output)
|
||||
{
|
||||
if ( !output ) return ErrorInternal;
|
||||
|
||||
if (cii(call_index, av->msi_session)) {
|
||||
LOGGER_WARNING("Invalid call index: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
pthread_mutex_lock(&call->mutex);
|
||||
|
||||
if (!call->call_active) {
|
||||
pthread_mutex_unlock(&call->mutex);
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
uint8_t packet [RTP_PAYLOAD_SIZE];
|
||||
int recved_size;
|
||||
|
||||
while ((recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet)) > 0) {
|
||||
if (recved_size < VIDEOFRAME_HEADER_SIZE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t i = packet[0] - call->frame_id;
|
||||
|
||||
if (i == 0) {
|
||||
/* piece of current frame */
|
||||
} else if (i > 0 && i < 128) {
|
||||
/* recieved a piece of a frame ahead, flush current frame and start reading this new frame */
|
||||
int rc = vpx_codec_decode(&call->cs->v_decoder, call->frame_buf, call->frame_limit, NULL, 0);
|
||||
call->frame_id = packet[0];
|
||||
memset(call->frame_buf, 0, call->frame_limit);
|
||||
call->frame_limit = 0;
|
||||
|
||||
if (rc != VPX_CODEC_OK) {
|
||||
LOGGER_ERROR("Error decoding video: %u %s\n", i, vpx_codec_err_to_string(rc));
|
||||
}
|
||||
} else {
|
||||
/* old packet, dont read */
|
||||
LOGGER_DEBUG("Old packet: %u\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (packet[1] > (MAX_VIDEOFRAME_SIZE - VIDEOFRAME_PIECE_SIZE + 1) /
|
||||
VIDEOFRAME_PIECE_SIZE) { //TODO, fix this check? not sure
|
||||
/* packet out of buffer range */
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGGER_DEBUG("Video Packet: %u %u\n", packet[0], packet[1]);
|
||||
memcpy(call->frame_buf + packet[1] * VIDEOFRAME_PIECE_SIZE, packet + VIDEOFRAME_HEADER_SIZE,
|
||||
recved_size - VIDEOFRAME_HEADER_SIZE);
|
||||
uint32_t limit = packet[1] * VIDEOFRAME_PIECE_SIZE + recved_size - VIDEOFRAME_HEADER_SIZE;
|
||||
|
||||
if (limit > call->frame_limit) {
|
||||
call->frame_limit = limit;
|
||||
LOGGER_DEBUG("Limit: %u\n", call->frame_limit);
|
||||
}
|
||||
}
|
||||
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img;
|
||||
img = vpx_codec_get_frame(&call->cs->v_decoder, &iter);
|
||||
|
||||
*output = img;
|
||||
|
||||
pthread_mutex_unlock(&call->mutex);
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode and send video packet.
|
||||
*
|
||||
|
@ -703,67 +599,6 @@ inline__ int toxav_prepare_video_frame(ToxAv *av, int32_t call_index, uint8_t *d
|
|||
return copied;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive decoded audio frame.
|
||||
*
|
||||
* @param av Handler.
|
||||
* @param frame_size The size of dest in frames/samples (one frame/sample is 16 bits or 2 bytes
|
||||
* and corresponds to one sample of audio.)
|
||||
* @param dest Destination of the raw audio (16 bit signed pcm with AUDIO_CHANNELS channels).
|
||||
* Make sure it has enough space for frame_size frames/samples.
|
||||
* @return int
|
||||
* @retval >=0 Size of received data in frames/samples.
|
||||
* @retval ToxAvError On error.
|
||||
*/
|
||||
inline__ int toxav_recv_audio ( ToxAv *av, int32_t call_index, int frame_size, int16_t *dest )
|
||||
{
|
||||
if ( !dest ) return ErrorInternal;
|
||||
|
||||
if (cii(call_index, av->msi_session)) {
|
||||
LOGGER_WARNING("Invalid call index: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
pthread_mutex_lock(&call->mutex);
|
||||
|
||||
|
||||
if (!call->call_active) {
|
||||
pthread_mutex_unlock(&call->mutex);
|
||||
LOGGER_WARNING("Action on inactive call: %d", call_index);
|
||||
return ErrorNoCall;
|
||||
}
|
||||
|
||||
uint8_t packet [RTP_PAYLOAD_SIZE];
|
||||
|
||||
int recved_size = toxav_recv_rtp_payload(av, call_index, TypeAudio, packet);
|
||||
|
||||
if ( recved_size == ErrorAudioPacketLost ) {
|
||||
int dec_size = opus_decode(call->cs->audio_decoder, NULL, 0, dest, frame_size, 1);
|
||||
|
||||
pthread_mutex_unlock(&call->mutex);
|
||||
|
||||
if ( dec_size < 0 ) {
|
||||
LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size));
|
||||
return ErrorInternal;
|
||||
} else return dec_size;
|
||||
|
||||
} else if ( recved_size ) {
|
||||
int dec_size = opus_decode(call->cs->audio_decoder, packet, recved_size, dest, frame_size, 0);
|
||||
|
||||
pthread_mutex_unlock(&call->mutex);
|
||||
|
||||
if ( dec_size < 0 ) {
|
||||
LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size));
|
||||
return ErrorInternal;
|
||||
} else return dec_size;
|
||||
} else {
|
||||
pthread_mutex_unlock(&call->mutex);
|
||||
return 0; /* Nothing received */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send audio frame.
|
||||
*
|
||||
|
@ -905,42 +740,6 @@ inline__ int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCa
|
|||
/* 0 is error here */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set queue limit
|
||||
*
|
||||
* @param av Handler
|
||||
* @param call_index index
|
||||
* @param limit the limit
|
||||
* @return void
|
||||
*/
|
||||
inline__ int toxav_set_audio_queue_limit(ToxAv *av, int32_t call_index, uint64_t limit)
|
||||
{
|
||||
if ( av->calls[call_index].crtps[audio_index] )
|
||||
rtp_queue_adjust_limit(av->calls[call_index].crtps[audio_index], limit);
|
||||
else
|
||||
return ErrorNoRtpSession;
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set queue limit
|
||||
*
|
||||
* @param av Handler
|
||||
* @param call_index index
|
||||
* @param limit the limit
|
||||
* @return void
|
||||
*/
|
||||
inline__ int toxav_set_video_queue_limit(ToxAv *av, int32_t call_index, uint64_t limit)
|
||||
{
|
||||
if ( av->calls[call_index].crtps[video_index] )
|
||||
rtp_queue_adjust_limit(av->calls[call_index].crtps[video_index], limit);
|
||||
else
|
||||
return ErrorNoRtpSession;
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
inline__ Tox *toxav_get_tox(ToxAv *av)
|
||||
{
|
||||
return (Tox *)av->messenger;
|
||||
|
@ -952,3 +751,89 @@ int toxav_has_activity(ToxAv *av, int32_t call_index, int16_t *PCM, uint16_t fra
|
|||
|
||||
return energy_VAD(av->calls[call_index].cs, PCM, frame_size, ref_energy);
|
||||
}
|
||||
|
||||
void toxav_handle_packet(RTPSession *_session, RTPMessage *_msg)
|
||||
{
|
||||
ToxAv *av = _session->av;
|
||||
int32_t call_index = _session->call_index;
|
||||
CallSpecific *call = &av->calls[call_index];
|
||||
|
||||
if (_session->payload_type == type_audio % 128) {
|
||||
queue(call->j_buf, _msg);
|
||||
|
||||
int success = 0, dec_size;
|
||||
int frame_size = 960;
|
||||
int16_t dest[frame_size];
|
||||
|
||||
while ((_msg = dequeue(call->j_buf, &success)) || success == 2) {
|
||||
if (success == 2) {
|
||||
dec_size = opus_decode(call->cs->audio_decoder, NULL, 0, dest, frame_size, 1);
|
||||
} else {
|
||||
dec_size = opus_decode(call->cs->audio_decoder, _msg->data, _msg->length, dest, frame_size, 0);
|
||||
rtp_free_msg(NULL, _msg);
|
||||
}
|
||||
|
||||
if (dec_size < 0) {
|
||||
LOGGER_WARNING("Decoding error: %s", opus_strerror(dec_size));
|
||||
continue;
|
||||
}
|
||||
|
||||
av->audio_callback(av, call_index, dest, frame_size);
|
||||
}
|
||||
} else {
|
||||
uint8_t *packet = _msg->data;
|
||||
int recved_size = _msg->length;
|
||||
|
||||
if (recved_size < VIDEOFRAME_HEADER_SIZE) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
uint8_t i = packet[0] - call->frame_id;
|
||||
|
||||
if (i == 0) {
|
||||
/* piece of current frame */
|
||||
} else if (i > 0 && i < 128) {
|
||||
/* recieved a piece of a frame ahead, flush current frame and start reading this new frame */
|
||||
int rc = vpx_codec_decode(&call->cs->v_decoder, call->frame_buf, call->frame_limit, NULL, 0);
|
||||
call->frame_id = packet[0];
|
||||
memset(call->frame_buf, 0, call->frame_limit);
|
||||
call->frame_limit = 0;
|
||||
|
||||
if (rc != VPX_CODEC_OK) {
|
||||
LOGGER_ERROR("Error decoding video: %u %s\n", i, vpx_codec_err_to_string(rc));
|
||||
}
|
||||
} else {
|
||||
/* old packet, dont read */
|
||||
LOGGER_DEBUG("Old packet: %u\n", i);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (packet[1] > (MAX_VIDEOFRAME_SIZE - VIDEOFRAME_PIECE_SIZE + 1) /
|
||||
VIDEOFRAME_PIECE_SIZE) { //TODO, fix this check? not sure
|
||||
/* packet out of buffer range */
|
||||
goto end;
|
||||
}
|
||||
|
||||
LOGGER_DEBUG("Video Packet: %u %u\n", packet[0], packet[1]);
|
||||
memcpy(call->frame_buf + packet[1] * VIDEOFRAME_PIECE_SIZE, packet + VIDEOFRAME_HEADER_SIZE,
|
||||
recved_size - VIDEOFRAME_HEADER_SIZE);
|
||||
uint32_t limit = packet[1] * VIDEOFRAME_PIECE_SIZE + recved_size - VIDEOFRAME_HEADER_SIZE;
|
||||
|
||||
if (limit > call->frame_limit) {
|
||||
call->frame_limit = limit;
|
||||
LOGGER_DEBUG("Limit: %u\n", call->frame_limit);
|
||||
}
|
||||
|
||||
end:
|
||||
;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
vpx_image_t *img;
|
||||
img = vpx_codec_get_frame(&call->cs->v_decoder, &iter);
|
||||
|
||||
if (img) {
|
||||
av->video_callback(av, call_index, img);
|
||||
}
|
||||
|
||||
rtp_free_msg(NULL, _msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,6 +164,22 @@ void toxav_kill(ToxAv *av);
|
|||
*/
|
||||
void toxav_register_callstate_callback (ToxAVCallback callback, ToxAvCallbackID id, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Register callback for recieving audio data
|
||||
*
|
||||
* @param callback The callback
|
||||
* @return void
|
||||
*/
|
||||
void toxav_register_audio_recv_callback (ToxAv *av, void (*callback)(ToxAv *, int32_t, int16_t *, int));
|
||||
|
||||
/**
|
||||
* @brief Register callback for recieving video data
|
||||
*
|
||||
* @param callback The callback
|
||||
* @return void
|
||||
*/
|
||||
void toxav_register_video_recv_callback (ToxAv *av, void (*callback)(ToxAv *, int32_t, vpx_image_t *));
|
||||
|
||||
/**
|
||||
* @brief Call user. Use its friend_id.
|
||||
*
|
||||
|
@ -252,31 +268,6 @@ int toxav_prepare_transmission(ToxAv *av, int32_t call_index, ToxAvCodecSettings
|
|||
*/
|
||||
int toxav_kill_transmission(ToxAv *av, int32_t call_index);
|
||||
|
||||
/**
|
||||
* @brief Receive decoded video packet.
|
||||
*
|
||||
* @param av Handler.
|
||||
* @param output Storage.
|
||||
* @return int
|
||||
* @retval 0 Success.
|
||||
* @retval ToxAvError On Error.
|
||||
*/
|
||||
int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **output);
|
||||
|
||||
/**
|
||||
* @brief Receive decoded audio frame.
|
||||
*
|
||||
* @param av Handler.
|
||||
* @param frame_size The size of dest in frames/samples (one frame/sample is 16 bits or 2 bytes
|
||||
* and corresponds to one sample of audio.)
|
||||
* @param dest Destination of the raw audio (16 bit signed pcm with AUDIO_CHANNELS channels).
|
||||
* Make sure it has enough space for frame_size frames/samples.
|
||||
* @return int
|
||||
* @retval >=0 Size of received data in frames/samples.
|
||||
* @retval ToxAvError On error.
|
||||
*/
|
||||
int toxav_recv_audio( ToxAv *av, int32_t call_index, int frame_size, int16_t *dest );
|
||||
|
||||
/**
|
||||
* @brief Encode and send video packet.
|
||||
*
|
||||
|
@ -399,4 +390,4 @@ int toxav_has_activity ( ToxAv *av, int32_t call_index, int16_t *PCM, uint16_t f
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TOXAV */
|
||||
#endif /* __TOXAV */
|
||||
|
|
Loading…
Reference in New Issue
Block a user