diff --git a/toxav/msi.c b/toxav/msi.c index 79058c76..6c4f2637 100644 --- a/toxav/msi.c +++ b/toxav/msi.c @@ -116,7 +116,7 @@ typedef struct _MSIMessage { static struct _Callbacks { MSICallback function; void *data; -} callbacks[11] = {0}; +} callbacks[11] = {{0}}; inline__ void invoke_callback(int32_t call_index, MSICallbackID id) { @@ -736,13 +736,7 @@ int send_message ( MSISession *session, MSICall *call, MSIMessage *msg, uint32_t */ int call_id_bigger( const uint8_t *first, const uint8_t *second) { - int i = 0; - - for (; i < CALL_ID_LEN; i ++) { - - if ( first[i] != second[i] ) - return first[i] > second [i] ? 0 : 1; - } + return (memcmp(first, second, CALL_ID_LEN) < 0); } diff --git a/toxav/toxav.c b/toxav/toxav.c index 742898ea..e45ef874 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -40,6 +40,10 @@ /* Assume 60 fps*/ #define MAX_ENCODE_TIME_US ((1000 / 60) * 1000) +#define MAX_VIDEOFRAME_SIZE 0x40000 /* 256KiB */ +#define VIDEOFRAME_PIECE_SIZE 0x500 /* 1.25 KiB*/ +#define VIDEOFRAME_HEADER_SIZE 0x2 + #define inline__ inline __attribute__((always_inline)) @@ -58,6 +62,10 @@ typedef struct _CallSpecific { * reuse them really. */ JitterBuffer *j_buf; /** Jitter buffer for audio */ + + 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 */ } CallSpecific; @@ -324,6 +332,17 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, ToxAvCodecSettin LOGGER_ERROR("Error while starting video RTP session!\n"); return ErrorStartingVideoRtp; } + + call->frame_limit = 0; + call->frame_id = 0; + call->frame_outid = 0; + + call->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1); + + if (!call->frame_buf) { + return ErrorInternal; + } + } if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) return ErrorInternal; @@ -395,14 +414,51 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) * @retval -1 Failure. */ inline__ int toxav_send_rtp_payload ( ToxAv *av, int32_t call_index, ToxAvCallType type, const uint8_t *payload, - uint16_t length ) + unsigned int length ) { if (cii(call_index, av->msi_session)) return ErrorNoCall; - if ( av->calls[call_index].crtps[type - TypeAudio] ) - return rtp_send_msg ( av->calls[call_index].crtps[type - TypeAudio], av->msi_session->messenger_handle, payload, - length ); - else return -1; +#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]) { + if (type == TypeAudio) { + return send(payload, length); + } else { + if (length == 0 || length > MAX_VIDEOFRAME_SIZE) { + LOGGER_ERROR("Invalid video frame size: %u\n", length); + return -1; + } + + /* number of pieces - 1*/ + uint8_t numparts = (length - 1) / VIDEOFRAME_PIECE_SIZE; + + uint8_t load[3 + VIDEOFRAME_PIECE_SIZE]; + load[0] = av->calls[call_index].frame_outid++; + load[1] = 0; + + int i; + + for (i = 0; i < numparts; i++) { + memcpy(load + VIDEOFRAME_HEADER_SIZE, payload, VIDEOFRAME_PIECE_SIZE); + payload += VIDEOFRAME_PIECE_SIZE; + + if (send(load, VIDEOFRAME_HEADER_SIZE + VIDEOFRAME_PIECE_SIZE) != 0) { + return -1; + } + + load[1]++; + } + + /* remainder = length % VIDEOFRAME_PIECE_SIZE, VIDEOFRAME_PIECE_SIZE if = 0 */ + length = ((length - 1) % VIDEOFRAME_PIECE_SIZE) + 1; + memcpy(load + VIDEOFRAME_HEADER_SIZE, payload, length); + return send(load, VIDEOFRAME_HEADER_SIZE + length); + } + } else { + return -1; + } + +#undef send } /** @@ -477,21 +533,47 @@ inline__ int toxav_recv_video ( ToxAv *av, int32_t call_index, vpx_image_t **out uint8_t packet [RTP_PAYLOAD_SIZE]; CallSpecific *call = &av->calls[call_index]; - int recved_size = 0; + int recved_size; - do { - recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet); + while ((recved_size = toxav_recv_rtp_payload(av, call_index, TypeVideo, packet)) > 0) { + if (recved_size < VIDEOFRAME_HEADER_SIZE) { + continue; + } - if (recved_size > 0) { - int rc = vpx_codec_decode(&call->cs->v_decoder, packet, recved_size, NULL, 0); + 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: %s\n", vpx_codec_err_to_string(rc)); return ErrorInternal; } + } else { + /* old packet, dont read */ + continue; } - } while (recved_size > 0); + 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; + } + + 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; + } + } vpx_codec_iter_t iter = NULL; vpx_image_t *img; diff --git a/toxdns/toxdns.c b/toxdns/toxdns.c index 3eafc3de..7a7a052d 100644 --- a/toxdns/toxdns.c +++ b/toxdns/toxdns.c @@ -26,6 +26,7 @@ #endif #include "../toxcore/Messenger.h" +#include "../toxcore/logger.h" #include "toxdns.h" static const char base32[32] = {"abcdefghijklmnopqrstuvwxyz012345"}; @@ -143,7 +144,7 @@ int tox_generate_dns3_string(void *dns3_object, uint8_t *string, uint16_t string } if (end_len != string - old_str) { - printf("tox_generate_dns3_string Fail, %u != %u\n", end_len, string - old_str); + LOGGER_ERROR("tox_generate_dns3_string Fail, %u != %lu\n", end_len, string - old_str); return -1; }