summaryrefslogtreecommitdiff
path: root/toxav/toxav.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-11-29 16:09:24 -0500
committerirungentoo <irungentoo@gmail.com>2014-11-29 16:09:24 -0500
commit8deb032b2d9a77465a3c2b65a409787098e387cd (patch)
tree785fc1b1b975b712bb9a375af386f4de18f89663 /toxav/toxav.c
parenteafe0e6b0b83b4db3d79a9416d8aa33318fb12a7 (diff)
parente62ded3a6dfc1203418e3d7a2c936794c4c9ec1c (diff)
Merge branch 'mutex-1' of https://github.com/mannol/toxcore
Diffstat (limited to 'toxav/toxav.c')
-rw-r--r--toxav/toxav.c282
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
49const ToxAvCSettings av_DefaultSettings = { 48const ToxAvCSettings av_DefaultSettings = {
50 av_TypeAudio, 49 av_TypeAudio,
@@ -62,32 +61,28 @@ const ToxAvCSettings av_DefaultSettings = {
62static const uint32_t jbuf_capacity = 6; 61static const uint32_t jbuf_capacity = 6;
63static const uint8_t audio_index = 0, video_index = 1; 62static const uint8_t audio_index = 0, video_index = 1;
64 63
65typedef struct _CallSpecific { 64typedef 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
78struct _ToxAv { 71struct _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
91static const MSICSettings *msicsettings_cast (const ToxAvCSettings *from) 86static 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
105ToxAv *toxav_new( Tox *messenger, int32_t max_calls) 99ToxAv *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
176void toxav_do(ToxAv *av) 167void 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
209void toxav_register_audio_callback(ToxAvAudioCallback cb, void *userdata) 201void 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
214void toxav_register_video_callback(ToxAvVideoCallback cb, void *userdata) 207void 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
219int toxav_call (ToxAv *av, 213int toxav_call (ToxAv *av,
@@ -227,86 +221,46 @@ int toxav_call (ToxAv *av,
227 221
228int toxav_hangup ( ToxAv *av, int32_t call_index ) 222int 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
241int toxav_answer ( ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings ) 227int 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
254int toxav_reject ( ToxAv *av, int32_t call_index, const char *reason ) 232int 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
267int toxav_cancel ( ToxAv *av, int32_t call_index, int peer_id, const char *reason ) 237int 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
280int toxav_change_settings(ToxAv *av, int32_t call_index, const ToxAvCSettings *csettings) 242int 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
289int toxav_stop_call ( ToxAv *av, int32_t call_index ) 247int 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
298int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, int support_video ) 252int 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;
368error: 328error:
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
378int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) 338int 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
409static int toxav_send_rtp_payload(ToxAv *av, 369static 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
443int toxav_prepare_video_frame ( ToxAv *av, int32_t call_index, uint8_t *dest, int dest_max, vpx_image_t *input) 408int 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
495int toxav_send_video ( ToxAv *av, int32_t call_index, const uint8_t *frame, unsigned int frame_size) 460int 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
552int toxav_send_audio ( ToxAv *av, int32_t call_index, const uint8_t *data, unsigned int size) 517int 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
578int toxav_get_peer_csettings ( ToxAv *av, int32_t call_index, int peer, ToxAvCSettings *dest ) 540int 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
588int toxav_get_peer_id ( ToxAv *av, int32_t call_index, int peer ) 550int 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
597ToxAvCallState toxav_get_call_state(ToxAv *av, int32_t call_index) 559ToxAvCallState 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
606int toxav_capability_supported ( ToxAv *av, int32_t call_index, ToxAvCapabilities capability ) 568int 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
617int 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
627int 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
634int toxav_get_active_count(ToxAv *av) 579int 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.