diff options
author | irungentoo <irungentoo@gmail.com> | 2014-11-29 16:09:24 -0500 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2014-11-29 16:09:24 -0500 |
commit | 8deb032b2d9a77465a3c2b65a409787098e387cd (patch) | |
tree | 785fc1b1b975b712bb9a375af386f4de18f89663 /toxav/toxav.c | |
parent | eafe0e6b0b83b4db3d79a9416d8aa33318fb12a7 (diff) | |
parent | e62ded3a6dfc1203418e3d7a2c936794c4c9ec1c (diff) |
Merge branch 'mutex-1' of https://github.com/mannol/toxcore
Diffstat (limited to 'toxav/toxav.c')
-rw-r--r-- | toxav/toxav.c | 282 |
1 files changed, 113 insertions, 169 deletions
diff --git a/toxav/toxav.c b/toxav/toxav.c index 11f709b9..4d9d668d 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -42,9 +42,8 @@ typedef struct Messenger Tox; | |||
42 | /* Assume 24 fps*/ | 42 | /* Assume 24 fps*/ |
43 | #define MAX_ENCODE_TIME_US ((1000 / 24) * 1000) | 43 | #define MAX_ENCODE_TIME_US ((1000 / 24) * 1000) |
44 | 44 | ||
45 | /* call index invalid: true if invalid */ | 45 | /* true if invalid call index */ |
46 | #define cii(c_idx, session) (c_idx < 0 || c_idx >= session->max_calls) | 46 | #define CALL_INVALID_INDEX(idx, max) (idx < 0 || idx >= max) |
47 | |||
48 | 47 | ||
49 | const ToxAvCSettings av_DefaultSettings = { | 48 | const ToxAvCSettings av_DefaultSettings = { |
50 | av_TypeAudio, | 49 | av_TypeAudio, |
@@ -62,32 +61,28 @@ const ToxAvCSettings av_DefaultSettings = { | |||
62 | static const uint32_t jbuf_capacity = 6; | 61 | static const uint32_t jbuf_capacity = 6; |
63 | static const uint8_t audio_index = 0, video_index = 1; | 62 | static const uint8_t audio_index = 0, video_index = 1; |
64 | 63 | ||
65 | typedef struct _CallSpecific { | 64 | typedef struct _ToxAvCall { |
65 | pthread_mutex_t mutex[1]; | ||
66 | RTPSession *crtps[2]; /** Audio is first and video is second */ | 66 | RTPSession *crtps[2]; /** Audio is first and video is second */ |
67 | CSSession *cs;/** Each call have its own encoders and decoders. | 67 | CSSession *cs; |
68 | * You can, but don't have to, reuse encoders for | 68 | _Bool active; |
69 | * multiple calls. If you choose to reuse encoders, | 69 | } ToxAvCall; |
70 | * make sure to also reuse encoded payload for every call. | ||
71 | * Decoders have to be unique for each call. | ||
72 | */ | ||
73 | |||
74 | _Bool call_active; | ||
75 | pthread_mutex_t mutex; | ||
76 | } CallSpecific; | ||
77 | 70 | ||
78 | struct _ToxAv { | 71 | struct _ToxAv { |
79 | Messenger *messenger; | 72 | Messenger *messenger; |
80 | MSISession *msi_session; /** Main msi session */ | 73 | MSISession *msi_session; /** Main msi session */ |
81 | CallSpecific *calls; /** Per-call params */ | 74 | ToxAvCall *calls; /** Per-call params */ |
82 | uint32_t max_calls; | 75 | uint32_t max_calls; |
83 | 76 | ||
77 | PAIR(ToxAvAudioCallback, void *) acb; | ||
78 | PAIR(ToxAvVideoCallback, void *) vcb; | ||
79 | |||
84 | /* Decode time measure */ | 80 | /* Decode time measure */ |
85 | int32_t dectmsscount; /** Measure count */ | 81 | int32_t dectmsscount; /** Measure count */ |
86 | int32_t dectmsstotal; /** Last cycle total */ | 82 | int32_t dectmsstotal; /** Last cycle total */ |
87 | int32_t avgdectms; /** Average decoding time in ms */ | 83 | int32_t avgdectms; /** Average decoding time in ms */ |
88 | }; | 84 | }; |
89 | 85 | ||
90 | |||
91 | static const MSICSettings *msicsettings_cast (const ToxAvCSettings *from) | 86 | static const MSICSettings *msicsettings_cast (const ToxAvCSettings *from) |
92 | { | 87 | { |
93 | assert(sizeof(MSICSettings) == sizeof(ToxAvCSettings)); | 88 | assert(sizeof(MSICSettings) == sizeof(ToxAvCSettings)); |
@@ -101,7 +96,6 @@ static const ToxAvCSettings *toxavcsettings_cast (const MSICSettings *from) | |||
101 | 96 | ||
102 | } | 97 | } |
103 | 98 | ||
104 | |||
105 | ToxAv *toxav_new( Tox *messenger, int32_t max_calls) | 99 | ToxAv *toxav_new( Tox *messenger, int32_t max_calls) |
106 | { | 100 | { |
107 | ToxAv *av = calloc ( sizeof(ToxAv), 1); | 101 | ToxAv *av = calloc ( sizeof(ToxAv), 1); |
@@ -114,14 +108,14 @@ ToxAv *toxav_new( Tox *messenger, int32_t max_calls) | |||
114 | av->messenger = (Messenger *)messenger; | 108 | av->messenger = (Messenger *)messenger; |
115 | av->msi_session = msi_new(av->messenger, max_calls); | 109 | av->msi_session = msi_new(av->messenger, max_calls); |
116 | av->msi_session->agent_handler = av; | 110 | av->msi_session->agent_handler = av; |
117 | av->calls = calloc(sizeof(CallSpecific), max_calls); | 111 | av->calls = calloc(sizeof(ToxAvCall), max_calls); |
118 | av->max_calls = max_calls; | 112 | av->max_calls = max_calls; |
119 | 113 | ||
120 | unsigned int i; | 114 | unsigned int i; |
121 | 115 | ||
122 | for (i = 0; i < max_calls; ++i) { | 116 | for (i = 0; i < max_calls; ++i) { |
123 | if (pthread_mutex_init(&av->calls[i].mutex, NULL) != 0 ) { | 117 | if (create_recursive_mutex(av->calls[i].mutex) != 0 ) { |
124 | LOGGER_WARNING("Failed to init call mutex!"); | 118 | LOGGER_WARNING("Failed to init call(%u) mutex!", i); |
125 | msi_kill(av->msi_session); | 119 | msi_kill(av->msi_session); |
126 | 120 | ||
127 | free(av->calls); | 121 | free(av->calls); |
@@ -145,9 +139,10 @@ void toxav_kill ( ToxAv *av ) | |||
145 | if ( av->calls[i].crtps[video_index] ) | 139 | if ( av->calls[i].crtps[video_index] ) |
146 | rtp_kill(av->calls[i].crtps[video_index], av->msi_session->messenger_handle); | 140 | rtp_kill(av->calls[i].crtps[video_index], av->msi_session->messenger_handle); |
147 | 141 | ||
148 | if ( av->calls[i].cs ) cs_kill(av->calls[i].cs); | 142 | if ( av->calls[i].cs ) |
143 | cs_kill(av->calls[i].cs); | ||
149 | 144 | ||
150 | pthread_mutex_destroy(&av->calls[i].mutex); | 145 | pthread_mutex_destroy(av->calls[i].mutex); |
151 | } | 146 | } |
152 | 147 | ||
153 | msi_kill(av->msi_session); | 148 | msi_kill(av->msi_session); |
@@ -161,16 +156,12 @@ uint32_t toxav_do_interval(ToxAv *av) | |||
161 | int i = 0; | 156 | int i = 0; |
162 | uint32_t rc = 200 + av->avgdectms; /* Return 200 if no call is active */ | 157 | uint32_t rc = 200 + av->avgdectms; /* Return 200 if no call is active */ |
163 | 158 | ||
164 | for (; i < av->max_calls; i ++) if (av->calls[i].call_active) { | 159 | for (; i < av->max_calls; i ++) if (av->calls[i].active) { |
165 | /* This should work. Video payload will always come in greater intervals */ | 160 | /* This should work. Video payload will always come in greater intervals */ |
166 | rc = MIN(av->calls[i].cs->audio_decoder_frame_duration, rc); | 161 | rc = MIN(av->calls[i].cs->audio_decoder_frame_duration, rc); |
167 | } | 162 | } |
168 | 163 | ||
169 | if (rc < av->avgdectms) { | 164 | return rc < av->avgdectms ? 0 : rc - av->avgdectms; |
170 | return 0; | ||
171 | } else { | ||
172 | return rc - av->avgdectms; | ||
173 | } | ||
174 | } | 165 | } |
175 | 166 | ||
176 | void toxav_do(ToxAv *av) | 167 | void toxav_do(ToxAv *av) |
@@ -182,11 +173,12 @@ void toxav_do(ToxAv *av) | |||
182 | uint32_t i = 0; | 173 | uint32_t i = 0; |
183 | 174 | ||
184 | for (; i < av->max_calls; i ++) { | 175 | for (; i < av->max_calls; i ++) { |
185 | pthread_mutex_lock(&av->calls[i].mutex); | 176 | pthread_mutex_lock(av->calls[i].mutex); |
186 | 177 | ||
187 | if (av->calls[i].call_active) cs_do(av->calls[i].cs); | 178 | if (av->calls[i].active) |
179 | cs_do(av->calls[i].cs); | ||
188 | 180 | ||
189 | pthread_mutex_unlock(&av->calls[i].mutex); | 181 | pthread_mutex_unlock(av->calls[i].mutex); |
190 | } | 182 | } |
191 | 183 | ||
192 | uint64_t end = current_time_monotonic(); | 184 | uint64_t end = current_time_monotonic(); |
@@ -206,14 +198,16 @@ void toxav_register_callstate_callback ( ToxAv *av, ToxAVCallback cb, ToxAvCallb | |||
206 | msi_register_callback(av->msi_session, (MSICallbackType)cb, (MSICallbackID) id, userdata); | 198 | msi_register_callback(av->msi_session, (MSICallbackType)cb, (MSICallbackID) id, userdata); |
207 | } | 199 | } |
208 | 200 | ||
209 | void toxav_register_audio_callback(ToxAvAudioCallback cb, void *userdata) | 201 | void toxav_register_audio_callback(ToxAv *av, ToxAvAudioCallback cb, void *userdata) |
210 | { | 202 | { |
211 | cs_register_audio_callback(cb, userdata); | 203 | av->acb.first = cb; |
204 | av->acb.second = userdata; | ||
212 | } | 205 | } |
213 | 206 | ||
214 | void toxav_register_video_callback(ToxAvVideoCallback cb, void *userdata) | 207 | void toxav_register_video_callback(ToxAv *av, ToxAvVideoCallback cb, void *userdata) |
215 | { | 208 | { |
216 | cs_register_video_callback(cb, userdata); | 209 | av->vcb.first = cb; |
210 | av->vcb.second = userdata; | ||
217 | } | 211 | } |
218 | 212 | ||
219 | int toxav_call (ToxAv *av, | 213 | int toxav_call (ToxAv *av, |
@@ -227,86 +221,46 @@ int toxav_call (ToxAv *av, | |||
227 | 221 | ||
228 | int toxav_hangup ( ToxAv *av, int32_t call_index ) | 222 | int toxav_hangup ( ToxAv *av, int32_t call_index ) |
229 | { | 223 | { |
230 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { | ||
231 | return av_ErrorNoCall; | ||
232 | } | ||
233 | |||
234 | if ( av->msi_session->calls[call_index]->state != call_active ) { | ||
235 | return av_ErrorInvalidState; | ||
236 | } | ||
237 | |||
238 | return msi_hangup(av->msi_session, call_index); | 224 | return msi_hangup(av->msi_session, call_index); |
239 | } | 225 | } |
240 | 226 | ||
241 | int toxav_answer ( ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings ) | 227 | int toxav_answer ( ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings ) |
242 | { | 228 | { |
243 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { | ||
244 | return av_ErrorNoCall; | ||
245 | } | ||
246 | |||
247 | if ( av->msi_session->calls[call_index]->state != call_starting ) { | ||
248 | return av_ErrorInvalidState; | ||
249 | } | ||
250 | |||
251 | return msi_answer(av->msi_session, call_index, msicsettings_cast(csettings)); | 229 | return msi_answer(av->msi_session, call_index, msicsettings_cast(csettings)); |
252 | } | 230 | } |
253 | 231 | ||
254 | int toxav_reject ( ToxAv *av, int32_t call_index, const char *reason ) | 232 | int toxav_reject ( ToxAv *av, int32_t call_index, const char *reason ) |
255 | { | 233 | { |
256 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { | ||
257 | return av_ErrorNoCall; | ||
258 | } | ||
259 | |||
260 | if ( av->msi_session->calls[call_index]->state != call_starting ) { | ||
261 | return av_ErrorInvalidState; | ||
262 | } | ||
263 | |||
264 | return msi_reject(av->msi_session, call_index, reason); | 234 | return msi_reject(av->msi_session, call_index, reason); |
265 | } | 235 | } |
266 | 236 | ||
267 | int toxav_cancel ( ToxAv *av, int32_t call_index, int peer_id, const char *reason ) | 237 | int toxav_cancel ( ToxAv *av, int32_t call_index, int peer_id, const char *reason ) |
268 | { | 238 | { |
269 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { | ||
270 | return av_ErrorNoCall; | ||
271 | } | ||
272 | |||
273 | if ( av->msi_session->calls[call_index]->state != call_inviting ) { | ||
274 | return av_ErrorInvalidState; | ||
275 | } | ||
276 | |||
277 | return msi_cancel(av->msi_session, call_index, peer_id, reason); | 239 | return msi_cancel(av->msi_session, call_index, peer_id, reason); |
278 | } | 240 | } |
279 | 241 | ||
280 | int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings) | 242 | int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings) |
281 | { | 243 | { |
282 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { | ||
283 | return av_ErrorNoCall; | ||
284 | } | ||
285 | |||
286 | return msi_change_csettings(av->msi_session, call_index, msicsettings_cast(csettings)); | 244 | return msi_change_csettings(av->msi_session, call_index, msicsettings_cast(csettings)); |
287 | } | 245 | } |
288 | 246 | ||
289 | int toxav_stop_call ( ToxAv *av, int32_t call_index ) | 247 | int toxav_stop_call ( ToxAv *av, int32_t call_index ) |
290 | { | 248 | { |
291 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) { | ||
292 | return av_ErrorNoCall; | ||
293 | } | ||
294 | |||
295 | return msi_stopcall(av->msi_session, call_index); | 249 | return msi_stopcall(av->msi_session, call_index); |
296 | } | 250 | } |
297 | 251 | ||
298 | int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, int support_video ) | 252 | int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, int support_video ) |
299 | { | 253 | { |
300 | if ( !av->msi_session || cii(call_index, av->msi_session) || | 254 | if ( !av->msi_session || CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) || |
301 | !av->msi_session->calls[call_index] || !av->msi_session->calls[call_index]->csettings_peer || | 255 | !av->msi_session->calls[call_index] || !av->msi_session->calls[call_index]->csettings_peer || |
302 | av->calls[call_index].call_active) { | 256 | av->calls[call_index].active) { |
303 | LOGGER_ERROR("Error while starting RTP session: invalid call!\n"); | 257 | LOGGER_ERROR("Error while starting RTP session: invalid call!\n"); |
304 | return av_ErrorInternal; | 258 | return av_ErrorNoCall; |
305 | } | 259 | } |
306 | 260 | ||
307 | CallSpecific *call = &av->calls[call_index]; | 261 | ToxAvCall *call = &av->calls[call_index]; |
308 | 262 | ||
309 | pthread_mutex_lock(&call->mutex); | 263 | pthread_mutex_lock(call->mutex); |
310 | const ToxAvCSettings *c_peer = toxavcsettings_cast | 264 | const ToxAvCSettings *c_peer = toxavcsettings_cast |
311 | (&av->msi_session->calls[call_index]->csettings_peer[0]); | 265 | (&av->msi_session->calls[call_index]->csettings_peer[0]); |
312 | const ToxAvCSettings *c_self = toxavcsettings_cast | 266 | const ToxAvCSettings *c_self = toxavcsettings_cast |
@@ -332,27 +286,33 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, int support_vide | |||
332 | 286 | ||
333 | if ( !(call->cs = cs_new(c_self, c_peer, jbuf_capacity, support_video)) ) { | 287 | if ( !(call->cs = cs_new(c_self, c_peer, jbuf_capacity, support_video)) ) { |
334 | LOGGER_ERROR("Error while starting Codec State!\n"); | 288 | LOGGER_ERROR("Error while starting Codec State!\n"); |
335 | pthread_mutex_unlock(&call->mutex); | 289 | pthread_mutex_unlock(call->mutex); |
336 | return av_ErrorInternal; | 290 | return av_ErrorInitializingCodecs; |
337 | } | 291 | } |
338 | 292 | ||
339 | call->cs->agent = av; | 293 | call->cs->agent = av; |
340 | call->cs->call_idx = call_index; | 294 | call->cs->call_idx = call_index; |
341 | 295 | ||
296 | call->cs->acb.first = av->acb.first; | ||
297 | call->cs->acb.second = av->acb.second; | ||
298 | |||
299 | call->cs->vcb.first = av->vcb.first; | ||
300 | call->cs->vcb.second = av->vcb.second; | ||
301 | |||
302 | |||
342 | call->crtps[audio_index] = | 303 | call->crtps[audio_index] = |
343 | rtp_new(type_audio, av->messenger, av->msi_session->calls[call_index]->peers[0]); | 304 | rtp_new(msi_TypeAudio, av->messenger, av->msi_session->calls[call_index]->peers[0]); |
344 | 305 | ||
345 | if ( !call->crtps[audio_index] ) { | 306 | if ( !call->crtps[audio_index] ) { |
346 | LOGGER_ERROR("Error while starting audio RTP session!\n"); | 307 | LOGGER_ERROR("Error while starting audio RTP session!\n"); |
347 | pthread_mutex_unlock(&call->mutex); | 308 | goto error; |
348 | return av_ErrorInternal; | ||
349 | } | 309 | } |
350 | 310 | ||
351 | call->crtps[audio_index]->cs = call->cs; | 311 | call->crtps[audio_index]->cs = call->cs; |
352 | 312 | ||
353 | if ( support_video ) { | 313 | if ( support_video ) { |
354 | call->crtps[video_index] = | 314 | call->crtps[video_index] = |
355 | rtp_new(type_video, av->messenger, av->msi_session->calls[call_index]->peers[0]); | 315 | rtp_new(msi_TypeVideo, av->messenger, av->msi_session->calls[call_index]->peers[0]); |
356 | 316 | ||
357 | if ( !call->crtps[video_index] ) { | 317 | if ( !call->crtps[video_index] ) { |
358 | LOGGER_ERROR("Error while starting video RTP session!\n"); | 318 | LOGGER_ERROR("Error while starting video RTP session!\n"); |
@@ -362,36 +322,38 @@ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, int support_vide | |||
362 | call->crtps[video_index]->cs = call->cs; | 322 | call->crtps[video_index]->cs = call->cs; |
363 | } | 323 | } |
364 | 324 | ||
365 | call->call_active = 1; | 325 | call->active = 1; |
366 | pthread_mutex_unlock(&call->mutex); | 326 | pthread_mutex_unlock(call->mutex); |
367 | return av_ErrorNone; | 327 | return av_ErrorNone; |
368 | error: | 328 | error: |
369 | rtp_kill(call->crtps[audio_index], av->messenger); | 329 | rtp_kill(call->crtps[audio_index], av->messenger); |
370 | rtp_kill(call->crtps[video_index], av->messenger); | 330 | rtp_kill(call->crtps[video_index], av->messenger); |
371 | cs_kill(call->cs); | 331 | cs_kill(call->cs); |
372 | memset(call, 0, sizeof(CallSpecific)); | 332 | memset(call, 0, sizeof(ToxAvCall)); |
373 | 333 | ||
374 | pthread_mutex_unlock(&call->mutex); | 334 | pthread_mutex_unlock(call->mutex); |
375 | return av_ErrorInternal; | 335 | return av_ErrorCreatingRtpSessions; |
376 | } | 336 | } |
377 | 337 | ||
378 | int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) | 338 | int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) |
379 | { | 339 | { |
380 | if (cii(call_index, av->msi_session)) { | 340 | if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls)) { |
381 | LOGGER_WARNING("Invalid call index: %d", call_index); | 341 | LOGGER_WARNING("Invalid call index: %d", call_index); |
382 | return av_ErrorNoCall; | 342 | return av_ErrorNoCall; |
383 | } | 343 | } |
384 | 344 | ||
385 | CallSpecific *call = &av->calls[call_index]; | 345 | ToxAvCall *call = &av->calls[call_index]; |
386 | 346 | ||
387 | pthread_mutex_lock(&call->mutex); | 347 | pthread_mutex_lock(call->mutex); |
388 | 348 | ||
389 | if (!call->call_active) { | 349 | if (!call->active) { |
390 | pthread_mutex_unlock(&call->mutex); | 350 | pthread_mutex_unlock(call->mutex); |
391 | LOGGER_WARNING("Action on inactive call: %d", call_index); | 351 | LOGGER_WARNING("Action on inactive call: %d", call_index); |
392 | return av_ErrorNoCall; | 352 | return av_ErrorInvalidState; |
393 | } | 353 | } |
394 | 354 | ||
355 | call->active = 0; | ||
356 | |||
395 | rtp_kill(call->crtps[audio_index], av->messenger); | 357 | rtp_kill(call->crtps[audio_index], av->messenger); |
396 | call->crtps[audio_index] = NULL; | 358 | call->crtps[audio_index] = NULL; |
397 | rtp_kill(call->crtps[video_index], av->messenger); | 359 | rtp_kill(call->crtps[video_index], av->messenger); |
@@ -399,19 +361,22 @@ int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) | |||
399 | cs_kill(call->cs); | 361 | cs_kill(call->cs); |
400 | call->cs = NULL; | 362 | call->cs = NULL; |
401 | 363 | ||
402 | call->call_active = 0; | 364 | pthread_mutex_unlock(call->mutex); |
403 | |||
404 | pthread_mutex_unlock(&call->mutex); | ||
405 | 365 | ||
406 | return av_ErrorNone; | 366 | return av_ErrorNone; |
407 | } | 367 | } |
408 | 368 | ||
409 | static int toxav_send_rtp_payload(ToxAv *av, | 369 | static int toxav_send_rtp_payload(ToxAv *av, |
410 | CallSpecific *call, | 370 | ToxAvCall *call, |
411 | ToxAvCallType type, | 371 | ToxAvCallType type, |
412 | const uint8_t *payload, | 372 | const uint8_t *payload, |
413 | unsigned int length) | 373 | unsigned int length) |
414 | { | 374 | { |
375 | if (length > MAX_CRYPTO_DATA_SIZE) { | ||
376 | LOGGER_WARNING("Size exceeds limit: %d", length); | ||
377 | return av_ErrorUnknown; | ||
378 | } | ||
379 | |||
415 | if (call->crtps[type - av_TypeAudio]) { | 380 | if (call->crtps[type - av_TypeAudio]) { |
416 | 381 | ||
417 | /* Audio */ | 382 | /* Audio */ |
@@ -421,7 +386,7 @@ static int toxav_send_rtp_payload(ToxAv *av, | |||
421 | /* Video */ | 386 | /* Video */ |
422 | int parts = cs_split_video_payload(call->cs, payload, length); | 387 | int parts = cs_split_video_payload(call->cs, payload, length); |
423 | 388 | ||
424 | if (parts == -1) return av_ErrorInternal; | 389 | if (parts < 0) return parts; |
425 | 390 | ||
426 | uint16_t part_size; | 391 | uint16_t part_size; |
427 | const uint8_t *iter; | 392 | const uint8_t *iter; |
@@ -431,8 +396,8 @@ static int toxav_send_rtp_payload(ToxAv *av, | |||
431 | for (i = 0; i < parts; i++) { | 396 | for (i = 0; i < parts; i++) { |
432 | iter = cs_get_split_video_frame(call->cs, &part_size); | 397 | iter = cs_get_split_video_frame(call->cs, &part_size); |
433 | 398 | ||
434 | if (rtp_send_msg(call->crtps[video_index], av->messenger, iter, part_size) != 0) | 399 | if (rtp_send_msg(call->crtps[video_index], av->messenger, iter, part_size) < 0) |
435 | return av_ErrorInternal; | 400 | return av_ErrorSendingPayload; |
436 | } | 401 | } |
437 | 402 | ||
438 | return av_ErrorNone; | 403 | return av_ErrorNone; |
@@ -442,32 +407,32 @@ static int toxav_send_rtp_payload(ToxAv *av, | |||
442 | 407 | ||
443 | int toxav_prepare_video_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input) | 408 | int toxav_prepare_video_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input) |
444 | { | 409 | { |
445 | if (cii(call_index, av->msi_session)) { | 410 | if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls)) { |
446 | LOGGER_WARNING("Invalid call index: %d", call_index); | 411 | LOGGER_WARNING("Invalid call index: %d", call_index); |
447 | return av_ErrorNoCall; | 412 | return av_ErrorNoCall; |
448 | } | 413 | } |
449 | 414 | ||
450 | 415 | ||
451 | CallSpecific *call = &av->calls[call_index]; | 416 | ToxAvCall *call = &av->calls[call_index]; |
452 | pthread_mutex_lock(&call->mutex); | 417 | pthread_mutex_lock(call->mutex); |
453 | 418 | ||
454 | if (!call->call_active) { | 419 | if (!call->active) { |
455 | pthread_mutex_unlock(&call->mutex); | 420 | pthread_mutex_unlock(call->mutex); |
456 | LOGGER_WARNING("Action on inactive call: %d", call_index); | 421 | LOGGER_WARNING("Action on inactive call: %d", call_index); |
457 | return av_ErrorNoCall; | 422 | return av_ErrorInvalidState; |
458 | } | 423 | } |
459 | 424 | ||
460 | if (cs_set_video_encoder_resolution(call->cs, input->d_w, input->d_h) != 0) { | 425 | if (cs_set_video_encoder_resolution(call->cs, input->d_w, input->d_h) < 0) { |
461 | pthread_mutex_unlock(&call->mutex); | 426 | pthread_mutex_unlock(call->mutex); |
462 | return av_ErrorInternal; | 427 | return av_ErrorSettingVideoResolution; |
463 | } | 428 | } |
464 | 429 | ||
465 | int rc = vpx_codec_encode(&call->cs->v_encoder, input, call->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); | 430 | int rc = vpx_codec_encode(&call->cs->v_encoder, input, call->cs->frame_counter, 1, 0, MAX_ENCODE_TIME_US); |
466 | 431 | ||
467 | if ( rc != VPX_CODEC_OK) { | 432 | if ( rc != VPX_CODEC_OK) { |
468 | LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(rc)); | 433 | LOGGER_ERROR("Could not encode video frame: %s\n", vpx_codec_err_to_string(rc)); |
469 | pthread_mutex_unlock(&call->mutex); | 434 | pthread_mutex_unlock(call->mutex); |
470 | return av_ErrorInternal; | 435 | return av_ErrorEncodingVideo; |
471 | } | 436 | } |
472 | 437 | ||
473 | ++call->cs->frame_counter; | 438 | ++call->cs->frame_counter; |
@@ -479,7 +444,7 @@ int toxav_prepare_video_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, in | |||
479 | while ( (pkt = vpx_codec_get_cx_data(&call->cs->v_encoder, &iter)) ) { | 444 | while ( (pkt = vpx_codec_get_cx_data(&call->cs->v_encoder, &iter)) ) { |
480 | if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { | 445 | if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { |
481 | if ( copied + pkt->data.frame.sz > dest_max ) { | 446 | if ( copied + pkt->data.frame.sz > dest_max ) { |
482 | pthread_mutex_unlock(&call->mutex); | 447 | pthread_mutex_unlock(call->mutex); |
483 | return av_ErrorPacketTooLarge; | 448 | return av_ErrorPacketTooLarge; |
484 | } | 449 | } |
485 | 450 | ||
@@ -488,30 +453,30 @@ int toxav_prepare_video_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, in | |||
488 | } | 453 | } |
489 | } | 454 | } |
490 | 455 | ||
491 | pthread_mutex_unlock(&call->mutex); | 456 | pthread_mutex_unlock(call->mutex); |
492 | return copied; | 457 | return copied; |
493 | } | 458 | } |
494 | 459 | ||
495 | int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, unsigned int frame_size) | 460 | int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, unsigned int frame_size) |
496 | { | 461 | { |
497 | 462 | ||
498 | if (cii(call_index, av->msi_session)) { | 463 | if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls)) { |
499 | LOGGER_WARNING("Invalid call index: %d", call_index); | 464 | LOGGER_WARNING("Invalid call index: %d", call_index); |
500 | return av_ErrorNoCall; | 465 | return av_ErrorNoCall; |
501 | } | 466 | } |
502 | 467 | ||
503 | CallSpecific *call = &av->calls[call_index]; | 468 | ToxAvCall *call = &av->calls[call_index]; |
504 | pthread_mutex_lock(&call->mutex); | 469 | pthread_mutex_lock(call->mutex); |
505 | 470 | ||
506 | 471 | ||
507 | if (!call->call_active) { | 472 | if (!call->active) { |
508 | pthread_mutex_unlock(&call->mutex); | 473 | pthread_mutex_unlock(call->mutex); |
509 | LOGGER_WARNING("Action on inactive call: %d", call_index); | 474 | LOGGER_WARNING("Action on inactive call: %d", call_index); |
510 | return av_ErrorNoCall; | 475 | return av_ErrorInvalidState; |
511 | } | 476 | } |
512 | 477 | ||
513 | int rc = toxav_send_rtp_payload(av, call, av_TypeVideo, frame, frame_size); | 478 | int rc = toxav_send_rtp_payload(av, call, av_TypeVideo, frame, frame_size); |
514 | pthread_mutex_unlock(&call->mutex); | 479 | pthread_mutex_unlock(call->mutex); |
515 | 480 | ||
516 | return rc; | 481 | return rc; |
517 | } | 482 | } |
@@ -523,27 +488,27 @@ int toxav_prepare_audio_frame ( ToxAv *av, | |||
523 | const int16_t *frame, | 488 | const int16_t *frame, |
524 | int frame_size) | 489 | int frame_size) |
525 | { | 490 | { |
526 | if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) { | 491 | if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) || !av->calls[call_index].active) { |
527 | LOGGER_WARNING("Action on inactive call: %d", call_index); | 492 | LOGGER_WARNING("Action on inactive call: %d", call_index); |
528 | return av_ErrorNoCall; | 493 | return av_ErrorNoCall; |
529 | } | 494 | } |
530 | 495 | ||
531 | CallSpecific *call = &av->calls[call_index]; | 496 | ToxAvCall *call = &av->calls[call_index]; |
532 | pthread_mutex_lock(&call->mutex); | 497 | pthread_mutex_lock(call->mutex); |
533 | 498 | ||
534 | 499 | ||
535 | if (!call->call_active) { | 500 | if (!call->active) { |
536 | pthread_mutex_unlock(&call->mutex); | 501 | pthread_mutex_unlock(call->mutex); |
537 | LOGGER_WARNING("Action on inactive call: %d", call_index); | 502 | LOGGER_WARNING("Action on inactive call: %d", call_index); |
538 | return av_ErrorNoCall; | 503 | return av_ErrorInvalidState; |
539 | } | 504 | } |
540 | 505 | ||
541 | int32_t rc = opus_encode(call->cs->audio_encoder, frame, frame_size, dest, dest_max); | 506 | int32_t rc = opus_encode(call->cs->audio_encoder, frame, frame_size, dest, dest_max); |
542 | pthread_mutex_unlock(&call->mutex); | 507 | pthread_mutex_unlock(call->mutex); |
543 | 508 | ||
544 | if (rc < 0) { | 509 | if (rc < 0) { |
545 | LOGGER_ERROR("Failed to encode payload: %s\n", opus_strerror(rc)); | 510 | LOGGER_ERROR("Failed to encode payload: %s\n", opus_strerror(rc)); |
546 | return av_ErrorInternal; | 511 | return av_ErrorEncodingAudio; |
547 | } | 512 | } |
548 | 513 | ||
549 | return rc; | 514 | return rc; |
@@ -551,35 +516,32 @@ int toxav_prepare_audio_frame ( ToxAv *av, | |||
551 | 516 | ||
552 | int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *data, unsigned int size) | 517 | int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *data, unsigned int size) |
553 | { | 518 | { |
554 | if (size > MAX_CRYPTO_DATA_SIZE) | 519 | if (CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) || !av->calls[call_index].active) { |
555 | return av_ErrorInternal; | ||
556 | |||
557 | if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) { | ||
558 | LOGGER_WARNING("Action on inactive call: %d", call_index); | 520 | LOGGER_WARNING("Action on inactive call: %d", call_index); |
559 | return av_ErrorNoCall; | 521 | return av_ErrorNoCall; |
560 | } | 522 | } |
561 | 523 | ||
562 | CallSpecific *call = &av->calls[call_index]; | 524 | ToxAvCall *call = &av->calls[call_index]; |
563 | pthread_mutex_lock(&call->mutex); | 525 | pthread_mutex_lock(call->mutex); |
564 | 526 | ||
565 | 527 | ||
566 | if (!call->call_active) { | 528 | if (!call->active) { |
567 | pthread_mutex_unlock(&call->mutex); | 529 | pthread_mutex_unlock(call->mutex); |
568 | LOGGER_WARNING("Action on inactive call: %d", call_index); | 530 | LOGGER_WARNING("Action on inactive call: %d", call_index); |
569 | return av_ErrorNoCall; | 531 | return av_ErrorInvalidState; |
570 | } | 532 | } |
571 | 533 | ||
572 | int rc = toxav_send_rtp_payload(av, call, av_TypeAudio, data, size); | 534 | int rc = toxav_send_rtp_payload(av, call, av_TypeAudio, data, size); |
573 | pthread_mutex_unlock(&call->mutex); | 535 | pthread_mutex_unlock(call->mutex); |
574 | 536 | ||
575 | return rc; | 537 | return rc; |
576 | } | 538 | } |
577 | 539 | ||
578 | int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings *dest ) | 540 | int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings *dest ) |
579 | { | 541 | { |
580 | if ( peer < 0 || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] | 542 | if ( peer < 0 || CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) || |
581 | || av->msi_session->calls[call_index]->peer_count <= peer ) | 543 | !av->msi_session->calls[call_index] || av->msi_session->calls[call_index]->peer_count <= peer ) |
582 | return av_ErrorInternal; | 544 | return av_ErrorNoCall; |
583 | 545 | ||
584 | *dest = *toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_peer[peer]); | 546 | *dest = *toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_peer[peer]); |
585 | return av_ErrorNone; | 547 | return av_ErrorNone; |
@@ -587,16 +549,16 @@ int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSe | |||
587 | 549 | ||
588 | int toxav_get_peer_id ( ToxAv *av, int32_t call_index, int peer ) | 550 | int toxav_get_peer_id ( ToxAv *av, int32_t call_index, int peer ) |
589 | { | 551 | { |
590 | if ( peer < 0 || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] | 552 | if ( peer < 0 || CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) || !av->msi_session->calls[call_index] |
591 | || av->msi_session->calls[call_index]->peer_count <= peer ) | 553 | || av->msi_session->calls[call_index]->peer_count <= peer ) |
592 | return av_ErrorInternal; | 554 | return av_ErrorNoCall; |
593 | 555 | ||
594 | return av->msi_session->calls[call_index]->peers[peer]; | 556 | return av->msi_session->calls[call_index]->peers[peer]; |
595 | } | 557 | } |
596 | 558 | ||
597 | ToxAvCallState toxav_get_call_state(ToxAv *av, int32_t call_index) | 559 | ToxAvCallState toxav_get_call_state(ToxAv *av, int32_t call_index) |
598 | { | 560 | { |
599 | if ( cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] ) | 561 | if ( CALL_INVALID_INDEX(call_index, av->msi_session->max_calls) || !av->msi_session->calls[call_index] ) |
600 | return av_CallNonExistent; | 562 | return av_CallNonExistent; |
601 | 563 | ||
602 | return av->msi_session->calls[call_index]->state; | 564 | return av->msi_session->calls[call_index]->state; |
@@ -605,7 +567,7 @@ ToxAvCallState toxav_get_call_state(ToxAv *av, int32_t call_index) | |||
605 | 567 | ||
606 | int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCapabilities capability ) | 568 | int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCapabilities capability ) |
607 | { | 569 | { |
608 | return av->calls[call_index].cs ? av->calls[call_index].cs->capabilities & (CsCapabilities) capability : 0; | 570 | return av->calls[call_index].cs ? av->calls[call_index].cs->capabilities & (CSCapabilities) capability : 0; |
609 | /* 0 is error here */ | 571 | /* 0 is error here */ |
610 | } | 572 | } |
611 | 573 | ||
@@ -614,35 +576,17 @@ Tox *toxav_get_tox(ToxAv *av) | |||
614 | return (Tox *)av->messenger; | 576 | return (Tox *)av->messenger; |
615 | } | 577 | } |
616 | 578 | ||
617 | int toxav_set_vad_treshold(ToxAv *av, int32_t call_index, uint32_t treshold) | ||
618 | { | ||
619 | if ( !av->calls[call_index].cs ) return av_ErrorInvalidCodecState; | ||
620 | |||
621 | /* TODO on't use default framedur... */ | ||
622 | cs_set_vad_treshold(av->calls[call_index].cs, treshold, av_DefaultSettings.audio_frame_duration); | ||
623 | |||
624 | return av_ErrorNone; | ||
625 | } | ||
626 | |||
627 | int toxav_has_activity(ToxAv *av, int32_t call_index, int16_t *PCM, uint16_t frame_size, float ref) | ||
628 | { | ||
629 | if ( !av->calls[call_index].cs ) return av_ErrorInvalidCodecState; | ||
630 | |||
631 | return cs_calculate_vad(av->calls[call_index].cs, PCM, frame_size, ref); | ||
632 | } | ||
633 | |||
634 | int toxav_get_active_count(ToxAv *av) | 579 | int toxav_get_active_count(ToxAv *av) |
635 | { | 580 | { |
636 | if (!av) return av_ErrorInternal; | 581 | if (!av) return -1; |
637 | 582 | ||
638 | int rc = 0, i = 0; | 583 | int rc = 0, i = 0; |
639 | 584 | ||
640 | for (; i < av->max_calls; i ++) if (av->calls[i].call_active) rc++; | 585 | for (; i < av->max_calls; i ++) if (av->calls[i].active) rc++; |
641 | 586 | ||
642 | return rc; | 587 | return rc; |
643 | } | 588 | } |
644 | 589 | ||
645 | |||
646 | /* Create a new toxav group. | 590 | /* Create a new toxav group. |
647 | * | 591 | * |
648 | * return group number on success. | 592 | * return group number on success. |