summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
Diffstat (limited to 'toxav')
-rw-r--r--toxav/codec.c160
-rw-r--r--toxav/codec.h14
-rw-r--r--toxav/rtp.c2
-rw-r--r--toxav/toxav.c47
-rw-r--r--toxav/toxav.h16
5 files changed, 93 insertions, 146 deletions
diff --git a/toxav/codec.c b/toxav/codec.c
index b7ca2784..1e8478bb 100644
--- a/toxav/codec.c
+++ b/toxav/codec.c
@@ -36,152 +36,96 @@
36#include "rtp.h" 36#include "rtp.h"
37#include "codec.h" 37#include "codec.h"
38 38
39const uint16_t min_jbuf_size = 4; 39JitterBuffer *create_queue(unsigned int capacity)
40const uint16_t min_readiness_idx = 2; /* when is buffer ready to dqq */
41
42int empty_queue(JitterBuffer *q)
43{ 40{
44 while (q->size > 0) { 41 unsigned int size = 1;
45 rtp_free_msg(NULL, q->queue[q->front]);
46 q->front++;
47
48 if (q->front == q->capacity)
49 q->front = 0;
50 42
51 q->size--; 43 while (size <= (capacity + 4) * 2) {
44 size *= 2;
52 } 45 }
53 46
54 q->id_set = 0;
55 q->queue_ready = 0;
56 return 0;
57}
58
59JitterBuffer *create_queue(int capacity)
60{
61 JitterBuffer *q; 47 JitterBuffer *q;
62 48
63 if ( !(q = calloc(sizeof(JitterBuffer), 1)) ) return NULL; 49 if ( !(q = calloc(sizeof(JitterBuffer), 1)) ) return NULL;
64 50
65 if (!(q->queue = calloc(sizeof(RTPMessage *), capacity))) { 51 if (!(q->queue = calloc(sizeof(RTPMessage *), size))) {
66 free(q); 52 free(q);
67 return NULL; 53 return NULL;
68 } 54 }
69 55
70 q->size = 0; 56 q->size = size;
71 q->capacity = capacity >= min_jbuf_size ? capacity : min_jbuf_size; 57 q->capacity = capacity;
72 q->front = 0;
73 q->rear = -1;
74 q->queue_ready = 0;
75 q->current_id = 0;
76 q->current_ts = 0;
77 q->id_set = 0;
78 return q; 58 return q;
79} 59}
80 60
61static void clear_queue(JitterBuffer *q)
62{
63 for (; q->bottom != q->top; ++q->bottom) {
64 if (q->queue[q->bottom % q->size]) {
65 rtp_free_msg(NULL, q->queue[q->bottom % q->size]);
66 q->queue[q->bottom % q->size] = NULL;
67 }
68 }
69}
70
81void terminate_queue(JitterBuffer *q) 71void terminate_queue(JitterBuffer *q)
82{ 72{
83 if (!q) return; 73 if (!q) return;
84 74
85 empty_queue(q); 75 clear_queue(q);
86 free(q->queue); 76 free(q->queue);
87
88 LOGGER_DEBUG("Terminated jitter buffer: %p", q);
89 free(q); 77 free(q);
90} 78}
91 79
92#define sequnum_older(sn_a, sn_b, ts_a, ts_b) (sn_a > sn_b || ts_a > ts_b) 80void queue(JitterBuffer *q, RTPMessage *pk)
93
94/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */
95RTPMessage *dequeue(JitterBuffer *q, int *success)
96{ 81{
97 if (q->size == 0 || q->queue_ready == 0) { /* Empty queue */ 82 uint16_t sequnum = pk->header->sequnum;
98 q->queue_ready = 0;
99 *success = 0;
100 return NULL;
101 }
102 83
103 int front = q->front; 84 unsigned int num = sequnum % q->size;
104 85
105 if (q->id_set == 0) { 86 if (sequnum - q->bottom > q->size) {
106 q->current_id = q->queue[front]->header->sequnum; 87 clear_queue(q);
107 q->current_ts = q->queue[front]->header->timestamp; 88 q->bottom = sequnum;
108 q->id_set = 1; 89 q->queue[num] = pk;
109 } else { 90 q->top = sequnum + 1;
110 int next_id = q->queue[front]->header->sequnum; 91 return;
111 int next_ts = q->queue[front]->header->timestamp;
112
113 /* if this packet is indeed the expected packet */
114 if (next_id == (q->current_id + 1) % MAX_SEQU_NUM) {
115 q->current_id = next_id;
116 q->current_ts = next_ts;
117 } else {
118 if (sequnum_older(next_id, q->current_id, next_ts, q->current_ts)) {
119 LOGGER_DEBUG("nextid: %d current: %d\n", next_id, q->current_id);
120 q->current_id = (q->current_id + 1) % MAX_SEQU_NUM;
121 *success = 2; /* tell the decoder the packet is lost */
122 return NULL;
123 } else {
124 LOGGER_DEBUG("Packet too old");
125 *success = 0;
126 return NULL;
127 }
128 }
129 } 92 }
130 93
131 q->size--; 94 if (q->queue[num])
132 q->front++; 95 return;
133 96
134 if (q->front == q->capacity) 97 q->queue[num] = pk;
135 q->front = 0;
136 98
137 *success = 1; 99 if ((sequnum - q->bottom) >= (q->top - q->bottom))
138 q->current_id = q->queue[front]->header->sequnum; 100 q->top = sequnum + 1;
139 q->current_ts = q->queue[front]->header->timestamp;
140 return q->queue[front];
141} 101}
142 102
143 103/* success is 0 when there is nothing to dequeue, 1 when there's a good packet, 2 when there's a lost packet */
144void queue(JitterBuffer *q, RTPMessage *pk) 104RTPMessage *dequeue(JitterBuffer *q, int *success)
145{ 105{
146 if (q->size == q->capacity) { /* Full, empty queue */ 106 if (q->top == q->bottom) {
147 LOGGER_DEBUG("Queue full s(%d) c(%d), emptying...", q->size, q->capacity); 107 *success = 0;
148 empty_queue(q); 108 return NULL;
149 } 109 }
150 110
151 if (q->size >= min_readiness_idx) q->queue_ready = 1; 111 unsigned int num = q->bottom % q->size;
152
153 ++q->size;
154 ++q->rear;
155
156 if (q->rear == q->capacity) q->rear = 0;
157 112
158 q->queue[q->rear] = pk; 113 if (q->queue[num]) {
159 114 RTPMessage *ret = q->queue[num];
160 int a; 115 q->queue[num] = NULL;
161 int j; 116 ++q->bottom;
162 a = q->rear; 117 *success = 1;
163 118 return ret;
164 for (j = 0; j < q->size - 1; ++j) { 119 }
165 int b = a - 1;
166
167 if (b < 0)
168 b += q->capacity;
169
170 if (sequnum_older(q->queue[b]->header->sequnum, q->queue[a]->header->sequnum,
171 q->queue[b]->header->timestamp, q->queue[a]->header->timestamp)) {
172 RTPMessage *temp;
173 temp = q->queue[a];
174 q->queue[a] = q->queue[b];
175 q->queue[b] = temp;
176 LOGGER_DEBUG("Had to swap");
177 } else {
178 break;
179 }
180
181 a -= 1;
182 120
183 if (a < 0) a += q->capacity; 121 if (q->top - q->bottom > q->capacity) {
122 ++q->bottom;
123 *success = 2;
124 return NULL;
184 } 125 }
126
127 *success = 0;
128 return NULL;
185} 129}
186 130
187 131
diff --git a/toxav/codec.h b/toxav/codec.h
index a464ec8f..755673f3 100644
--- a/toxav/codec.h
+++ b/toxav/codec.h
@@ -78,17 +78,13 @@ typedef struct _CodecState {
78 78
79typedef struct _JitterBuffer { 79typedef struct _JitterBuffer {
80 RTPMessage **queue; 80 RTPMessage **queue;
81 uint16_t capacity; 81 unsigned int size;
82 uint16_t size; 82 unsigned int capacity;
83 uint16_t front; 83 uint16_t bottom;
84 uint16_t rear; 84 uint16_t top;
85 uint8_t queue_ready;
86 uint16_t current_id;
87 uint32_t current_ts;
88 uint8_t id_set;
89} JitterBuffer; 85} JitterBuffer;
90 86
91JitterBuffer *create_queue(int capacity); 87JitterBuffer *create_queue(unsigned int capacity);
92void terminate_queue(JitterBuffer *q); 88void terminate_queue(JitterBuffer *q);
93void queue(JitterBuffer *q, RTPMessage *pk); 89void queue(JitterBuffer *q, RTPMessage *pk);
94RTPMessage *dequeue(JitterBuffer *q, int *success); 90RTPMessage *dequeue(JitterBuffer *q, int *success);
diff --git a/toxav/rtp.c b/toxav/rtp.c
index 17319f81..595c58cc 100644
--- a/toxav/rtp.c
+++ b/toxav/rtp.c
@@ -551,7 +551,7 @@ RTPSession *rtp_init_session ( int payload_type, Messenger *messenger, int frien
551 551
552 _retu->dest = friend_num; 552 _retu->dest = friend_num;
553 553
554 _retu->rsequnum = _retu->sequnum = 1; 554 _retu->rsequnum = _retu->sequnum = 0;
555 555
556 _retu->ext_header = NULL; /* When needed allocate */ 556 _retu->ext_header = NULL; /* When needed allocate */
557 557
diff --git a/toxav/toxav.c b/toxav/toxav.c
index e4b8fe2e..47a94fba 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -51,6 +51,24 @@
51/* call index invalid: true if invalid */ 51/* call index invalid: true if invalid */
52#define cii(c_idx, session) (c_idx < 0 || c_idx >= session->max_calls) 52#define cii(c_idx, session) (c_idx < 0 || c_idx >= session->max_calls)
53 53
54
55const ToxAvCSettings av_DefaultSettings = {
56 TypeAudio,
57
58 500,
59 1280,
60 720,
61
62 64000,
63 20,
64 48000,
65 1
66};
67
68const uint32_t av_jbufdc = 3;
69const uint32_t av_VADd = 40;
70
71
54static const uint8_t audio_index = 0, video_index = 1; 72static const uint8_t audio_index = 0, video_index = 1;
55 73
56typedef struct _CallSpecific { 74typedef struct _CallSpecific {
@@ -84,20 +102,7 @@ struct _ToxAv {
84 uint32_t max_calls; 102 uint32_t max_calls;
85}; 103};
86 104
87const ToxAvCodecSettings av_DefaultSettings = { 105static MSICSettings msicsettings_cast (const ToxAvCSettings* from)
88 TypeAudio,
89
90 500,
91 1280,
92 720,
93
94 64000,
95 20,
96 48000,
97 1
98};
99
100static MSICSettings msicsettings_cast (const ToxAvCodecSettings* from)
101{ 106{
102 MSICSettings csettings; 107 MSICSettings csettings;
103 csettings.call_type = from->call_type; 108 csettings.call_type = from->call_type;
@@ -114,9 +119,9 @@ static MSICSettings msicsettings_cast (const ToxAvCodecSettings* from)
114 return csettings; 119 return csettings;
115} 120}
116 121
117static ToxAvCodecSettings toxavcsettings_cast (const MSICSettings* from) 122static ToxAvCSettings toxavcsettings_cast (const MSICSettings* from)
118{ 123{
119 ToxAvCodecSettings csettings; 124 ToxAvCSettings csettings;
120 csettings.call_type = from->call_type; 125 csettings.call_type = from->call_type;
121 126
122 csettings.video_bitrate = from->video_bitrate; 127 csettings.video_bitrate = from->video_bitrate;
@@ -237,7 +242,7 @@ void toxav_register_video_recv_callback (ToxAv *av, void (*callback)(ToxAv *, in
237 * @retval 0 Success. 242 * @retval 0 Success.
238 * @retval ToxAvError On error. 243 * @retval ToxAvError On error.
239 */ 244 */
240int toxav_call (ToxAv* av, int32_t* call_index, int user, const ToxAvCodecSettings* csettings, int ringing_seconds ) 245int toxav_call (ToxAv* av, int32_t* call_index, int user, const ToxAvCSettings* csettings, int ringing_seconds )
241{ 246{
242 return msi_invite(av->msi_session, call_index, msicsettings_cast(csettings), ringing_seconds * 1000, user); 247 return msi_invite(av->msi_session, call_index, msicsettings_cast(csettings), ringing_seconds * 1000, user);
243} 248}
@@ -272,7 +277,7 @@ int toxav_hangup ( ToxAv *av, int32_t call_index )
272 * @retval 0 Success. 277 * @retval 0 Success.
273 * @retval ToxAvError On error. 278 * @retval ToxAvError On error.
274 */ 279 */
275int toxav_answer ( ToxAv* av, int32_t call_index, const ToxAvCodecSettings* csettings ) 280int toxav_answer ( ToxAv* av, int32_t call_index, const ToxAvCSettings* csettings )
276{ 281{
277 if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { 282 if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) {
278 return ErrorNoCall; 283 return ErrorNoCall;
@@ -339,7 +344,7 @@ int toxav_cancel ( ToxAv *av, int32_t call_index, int peer_id, const char *reaso
339 * @retval 0 Success. 344 * @retval 0 Success.
340 * @retval ToxAvError On error. 345 * @retval ToxAvError On error.
341 */ 346 */
342int toxav_change_settings(ToxAv* av, int32_t call_index, const ToxAvCodecSettings* csettings) 347int toxav_change_settings(ToxAv* av, int32_t call_index, const ToxAvCSettings* csettings)
343{ 348{
344 if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { 349 if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) {
345 return ErrorNoCall; 350 return ErrorNoCall;
@@ -426,7 +431,7 @@ int toxav_prepare_transmission ( ToxAv* av, int32_t call_index, uint32_t jbuf_ca
426 goto error; 431 goto error;
427 } 432 }
428 433
429 ToxAvCodecSettings csettings = toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_peer[0]); 434 ToxAvCSettings csettings = toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_peer[0]);
430 LOGGER_DEBUG( 435 LOGGER_DEBUG(
431 "Type: %u \n" 436 "Type: %u \n"
432 "Video bitrate: %u \n" 437 "Video bitrate: %u \n"
@@ -754,7 +759,7 @@ inline__ int toxav_prepare_audio_frame ( ToxAv *av, int32_t call_index, uint8_t
754 * @retval ToxAvCallType On success. 759 * @retval ToxAvCallType On success.
755 * @retval ToxAvError On error. 760 * @retval ToxAvError On error.
756 */ 761 */
757int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCodecSettings* dest ) 762int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings* dest )
758{ 763{
759 if ( peer < 0 || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] 764 if ( peer < 0 || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index]
760 || av->msi_session->calls[call_index]->peer_count <= peer ) 765 || av->msi_session->calls[call_index]->peer_count <= peer )
diff --git a/toxav/toxav.h b/toxav/toxav.h
index 384e09a6..4dfcd224 100644
--- a/toxav/toxav.h
+++ b/toxav/toxav.h
@@ -129,9 +129,11 @@ typedef struct _ToxAvCodecSettings {
129 uint16_t audio_frame_duration; /* In ms */ 129 uint16_t audio_frame_duration; /* In ms */
130 uint32_t audio_sample_rate; /* In Hz */ 130 uint32_t audio_sample_rate; /* In Hz */
131 uint32_t audio_channels; 131 uint32_t audio_channels;
132} ToxAvCodecSettings; 132} ToxAvCSettings;
133 133
134extern const ToxAvCodecSettings av_DefaultSettings; 134extern const ToxAvCSettings av_DefaultSettings;
135extern const uint32_t av_jbufdc; /* Jitter buffer default capacity */
136extern const uint32_t av_VADd; /* VAD default treshold */
135 137
136/** 138/**
137 * @brief Start new A/V session. There can only be one session at the time. If you register more 139 * @brief Start new A/V session. There can only be one session at the time. If you register more
@@ -193,7 +195,7 @@ void toxav_register_video_recv_callback (ToxAv *av, void (*callback)(ToxAv *, in
193 * @retval 0 Success. 195 * @retval 0 Success.
194 * @retval ToxAvError On error. 196 * @retval ToxAvError On error.
195 */ 197 */
196int toxav_call(ToxAv* av, int32_t* call_index, int user, const ToxAvCodecSettings* csettings, int ringing_seconds); 198int toxav_call(ToxAv* av, int32_t* call_index, int user, const ToxAvCSettings* csettings, int ringing_seconds);
197 199
198/** 200/**
199 * @brief Hangup active call. 201 * @brief Hangup active call.
@@ -214,7 +216,7 @@ int toxav_hangup(ToxAv *av, int32_t call_index);
214 * @retval 0 Success. 216 * @retval 0 Success.
215 * @retval ToxAvError On error. 217 * @retval ToxAvError On error.
216 */ 218 */
217int toxav_answer(ToxAv *av, int32_t call_index, const ToxAvCodecSettings* csettings ); 219int toxav_answer(ToxAv *av, int32_t call_index, const ToxAvCSettings* csettings );
218 220
219/** 221/**
220 * @brief Reject incomming call. 222 * @brief Reject incomming call.
@@ -240,14 +242,14 @@ int toxav_reject(ToxAv *av, int32_t call_index, const char *reason);
240int toxav_cancel(ToxAv *av, int32_t call_index, int peer_id, const char *reason); 242int toxav_cancel(ToxAv *av, int32_t call_index, int peer_id, const char *reason);
241 243
242/** 244/**
243 * @brief Notify peer that we are changing call type 245 * @brief Notify peer that we are changing call settings
244 * 246 *
245 * @param av Handler. 247 * @param av Handler.
246 * @return int 248 * @return int
247 * @retval 0 Success. 249 * @retval 0 Success.
248 * @retval ToxAvError On error. 250 * @retval ToxAvError On error.
249 */ 251 */
250int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCodecSettings* csettings); 252int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCSettings* csettings);
251 253
252/** 254/**
253 * @brief Terminate transmission. Note that transmission will be terminated without informing remote peer. 255 * @brief Terminate transmission. Note that transmission will be terminated without informing remote peer.
@@ -342,7 +344,7 @@ int toxav_prepare_audio_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, in
342 * @retval ToxAvCallType On success. 344 * @retval ToxAvCallType On success.
343 * @retval ToxAvError On error. 345 * @retval ToxAvError On error.
344 */ 346 */
345int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCodecSettings* dest ); 347int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings* dest );
346 348
347/** 349/**
348 * @brief Get id of peer participating in conversation 350 * @brief Get id of peer participating in conversation