diff options
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/codec.c | 160 | ||||
-rw-r--r-- | toxav/codec.h | 14 | ||||
-rw-r--r-- | toxav/rtp.c | 2 | ||||
-rw-r--r-- | toxav/toxav.c | 47 | ||||
-rw-r--r-- | toxav/toxav.h | 16 |
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 | ||
39 | const uint16_t min_jbuf_size = 4; | 39 | JitterBuffer *create_queue(unsigned int capacity) |
40 | const uint16_t min_readiness_idx = 2; /* when is buffer ready to dqq */ | ||
41 | |||
42 | int 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 | |||
59 | JitterBuffer *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 | ||
61 | static 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 | |||
81 | void terminate_queue(JitterBuffer *q) | 71 | void 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) | 80 | void 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 */ | ||
95 | RTPMessage *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 */ | |
144 | void queue(JitterBuffer *q, RTPMessage *pk) | 104 | RTPMessage *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 | ||
79 | typedef struct _JitterBuffer { | 79 | typedef 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 | ||
91 | JitterBuffer *create_queue(int capacity); | 87 | JitterBuffer *create_queue(unsigned int capacity); |
92 | void terminate_queue(JitterBuffer *q); | 88 | void terminate_queue(JitterBuffer *q); |
93 | void queue(JitterBuffer *q, RTPMessage *pk); | 89 | void queue(JitterBuffer *q, RTPMessage *pk); |
94 | RTPMessage *dequeue(JitterBuffer *q, int *success); | 90 | RTPMessage *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 | |||
55 | const ToxAvCSettings av_DefaultSettings = { | ||
56 | TypeAudio, | ||
57 | |||
58 | 500, | ||
59 | 1280, | ||
60 | 720, | ||
61 | |||
62 | 64000, | ||
63 | 20, | ||
64 | 48000, | ||
65 | 1 | ||
66 | }; | ||
67 | |||
68 | const uint32_t av_jbufdc = 3; | ||
69 | const uint32_t av_VADd = 40; | ||
70 | |||
71 | |||
54 | static const uint8_t audio_index = 0, video_index = 1; | 72 | static const uint8_t audio_index = 0, video_index = 1; |
55 | 73 | ||
56 | typedef struct _CallSpecific { | 74 | typedef struct _CallSpecific { |
@@ -84,20 +102,7 @@ struct _ToxAv { | |||
84 | uint32_t max_calls; | 102 | uint32_t max_calls; |
85 | }; | 103 | }; |
86 | 104 | ||
87 | const ToxAvCodecSettings av_DefaultSettings = { | 105 | static 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 | |||
100 | static 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 | ||
117 | static ToxAvCodecSettings toxavcsettings_cast (const MSICSettings* from) | 122 | static 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 | */ |
240 | int toxav_call (ToxAv* av, int32_t* call_index, int user, const ToxAvCodecSettings* csettings, int ringing_seconds ) | 245 | int 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 | */ |
275 | int toxav_answer ( ToxAv* av, int32_t call_index, const ToxAvCodecSettings* csettings ) | 280 | int 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 | */ |
342 | int toxav_change_settings(ToxAv* av, int32_t call_index, const ToxAvCodecSettings* csettings) | 347 | int 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 | */ |
757 | int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCodecSettings* dest ) | 762 | int 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 | ||
134 | extern const ToxAvCodecSettings av_DefaultSettings; | 134 | extern const ToxAvCSettings av_DefaultSettings; |
135 | extern const uint32_t av_jbufdc; /* Jitter buffer default capacity */ | ||
136 | extern 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 | */ |
196 | int toxav_call(ToxAv* av, int32_t* call_index, int user, const ToxAvCodecSettings* csettings, int ringing_seconds); | 198 | int 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 | */ |
217 | int toxav_answer(ToxAv *av, int32_t call_index, const ToxAvCodecSettings* csettings ); | 219 | int 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); | |||
240 | int toxav_cancel(ToxAv *av, int32_t call_index, int peer_id, const char *reason); | 242 | int 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 | */ |
250 | int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCodecSettings* csettings); | 252 | int 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 | */ |
345 | int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCodecSettings* dest ); | 347 | int 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 |