summaryrefslogtreecommitdiff
path: root/toxav
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-05-22 23:22:31 +0200
committermannol <eniz_vukovic@hotmail.com>2015-05-22 23:22:31 +0200
commit3100042a2b78f4f80d23f67e6113797cd8fb5df0 (patch)
treec226f4b25002784d93f9bb6415be4b55b76cddd1 /toxav
parent62c40af1a0c557ba8c77583c972ae3af9af15cf1 (diff)
parent2ba076ac5cc6efb5eb41fb4aa6a77a151885f26c (diff)
Updated with master
Diffstat (limited to 'toxav')
-rw-r--r--toxav/audio.c2
-rw-r--r--toxav/audio.h4
-rw-r--r--toxav/msi.c2
-rw-r--r--toxav/msi.h8
-rw-r--r--toxav/toxav.c374
-rw-r--r--toxav/toxav.h820
-rw-r--r--toxav/video.c7
-rw-r--r--toxav/video.h4
8 files changed, 746 insertions, 475 deletions
diff --git a/toxav/audio.c b/toxav/audio.c
index c592a7da..f6993a1d 100644
--- a/toxav/audio.c
+++ b/toxav/audio.c
@@ -38,7 +38,7 @@ bool reconfigure_audio_decoder(ACSession* ac, int32_t sampling_rate, int8_t chan
38 38
39 39
40 40
41ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data) 41ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_audio_receive_frame_cb *cb, void *cb_data)
42{ 42{
43 ACSession *ac = calloc(sizeof(ACSession), 1); 43 ACSession *ac = calloc(sizeof(ACSession), 1);
44 44
diff --git a/toxav/audio.h b/toxav/audio.h
index c003bac0..9ef10ae4 100644
--- a/toxav/audio.h
+++ b/toxav/audio.h
@@ -61,13 +61,13 @@ typedef struct ACSession_s {
61 61
62 ToxAV* av; 62 ToxAV* av;
63 uint32_t friend_number; 63 uint32_t friend_number;
64 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ 64 PAIR(toxav_audio_receive_frame_cb *, void *) acb; /* Audio frame receive callback */
65} ACSession; 65} ACSession;
66 66
67/* 67/*
68 * Create new Audio Codec session. 68 * Create new Audio Codec session.
69 */ 69 */
70ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data); 70ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_audio_receive_frame_cb *cb, void *cb_data);
71/* 71/*
72 * Kill the Audio Codec session. 72 * Kill the Audio Codec session.
73 */ 73 */
diff --git a/toxav/msi.c b/toxav/msi.c
index 65b6c4e4..d3559160 100644
--- a/toxav/msi.c
+++ b/toxav/msi.c
@@ -683,7 +683,7 @@ void handle_push ( MSICall *call, const MSIMessage *msg )
683 683
684 /* Only act if capabilities changed */ 684 /* Only act if capabilities changed */
685 if ( call->peer_capabilities != msg->capabilities.value) { 685 if ( call->peer_capabilities != msg->capabilities.value) {
686 LOGGER_INFO("Friend is changing capabilities"); 686 LOGGER_INFO("Friend is changing capabilities to: %u", msg->capabilities.value);
687 687
688 call->peer_capabilities = msg->capabilities.value; 688 call->peer_capabilities = msg->capabilities.value;
689 if ( invoke_callback(call, msi_OnCapabilities) == -1 ) 689 if ( invoke_callback(call, msi_OnCapabilities) == -1 )
diff --git a/toxav/msi.h b/toxav/msi.h
index 4836ae89..59f32c1d 100644
--- a/toxav/msi.h
+++ b/toxav/msi.h
@@ -50,10 +50,10 @@ typedef enum {
50 * Supported capabilities 50 * Supported capabilities
51 */ 51 */
52typedef enum { 52typedef enum {
53 msi_CapSAudio = 1, /* sending audio */ 53 msi_CapSAudio = 4, /* sending audio */
54 msi_CapSVideo = 2, /* sending video */ 54 msi_CapSVideo = 8, /* sending video */
55 msi_CapRAudio = 4, /* receiving audio */ 55 msi_CapRAudio = 16, /* receiving audio */
56 msi_CapRVideo = 8, /* receiving video */ 56 msi_CapRVideo = 32, /* receiving video */
57} MSICapabilities; 57} MSICapabilities;
58 58
59 59
diff --git a/toxav/toxav.c b/toxav/toxav.c
index 5e32f196..7ce6b9bc 100644
--- a/toxav/toxav.c
+++ b/toxav/toxav.c
@@ -91,8 +91,8 @@ struct ToxAV {
91 91
92 PAIR(toxav_call_cb *, void*) ccb; /* Call callback */ 92 PAIR(toxav_call_cb *, void*) ccb; /* Call callback */
93 PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */ 93 PAIR(toxav_call_state_cb *, void *) scb; /* Call state callback */
94 PAIR(toxav_receive_audio_frame_cb *, void *) acb; /* Audio frame receive callback */ 94 PAIR(toxav_audio_receive_frame_cb *, void *) acb; /* Audio frame receive callback */
95 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ 95 PAIR(toxav_video_receive_frame_cb *, void *) vcb; /* Video frame receive callback */
96 PAIR(toxav_audio_bit_rate_status_cb *, void *) abcb; /* Audio bit rate control callback */ 96 PAIR(toxav_audio_bit_rate_status_cb *, void *) abcb; /* Audio bit rate control callback */
97 PAIR(toxav_video_bit_rate_status_cb *, void *) vbcb; /* Video bit rate control callback */ 97 PAIR(toxav_video_bit_rate_status_cb *, void *) vbcb; /* Video bit rate control callback */
98 98
@@ -122,6 +122,27 @@ void call_kill_transmission(ToxAVCall* call);
122void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate); 122void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate);
123bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba); 123bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba);
124 124
125uint32_t toxav_version_major(void)
126{
127 return 0;
128}
129uint32_t toxav_version_minor(void)
130{
131 return 0;
132}
133uint32_t toxav_version_patch(void)
134{
135 return 0;
136}
137bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch)
138{
139 (void)major;
140 (void)minor;
141 (void)patch;
142
143 return 1;
144}
145
125ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error) 146ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error)
126{ 147{
127 TOXAV_ERR_NEW rc = TOXAV_ERR_NEW_OK; 148 TOXAV_ERR_NEW rc = TOXAV_ERR_NEW_OK;
@@ -204,7 +225,7 @@ void toxav_kill(ToxAV* av)
204 free(av); 225 free(av);
205} 226}
206 227
207Tox* toxav_get_tox(ToxAV* av) 228Tox* toxav_get_tox(const ToxAV* av)
208{ 229{
209 return (Tox*) av->m; 230 return (Tox*) av->m;
210} 231}
@@ -430,20 +451,14 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
430 goto END; 451 goto END;
431 } 452 }
432 453
433
434 ToxAVCall* call = call_get(av, friend_number); 454 ToxAVCall* call = call_get(av, friend_number);
435 if (call == NULL) { 455 if (call == NULL || (!call->active && control != TOXAV_CALL_CONTROL_CANCEL)) {
436 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; 456 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
437 goto END; 457 goto END;
438 } 458 }
439 459
440 switch (control) { 460 switch (control) {
441 case TOXAV_CALL_CONTROL_RESUME: { 461 case TOXAV_CALL_CONTROL_RESUME: {
442 if (!call->active) {
443 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
444 goto END;
445 }
446
447 /* Only act if paused and had media transfer active before */ 462 /* Only act if paused and had media transfer active before */
448 if (call->msi_call->self_capabilities == 0 && 463 if (call->msi_call->self_capabilities == 0 &&
449 call->previous_self_capabilities ) { 464 call->previous_self_capabilities ) {
@@ -459,17 +474,12 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
459 rtp_start_receiving(call->audio.first); 474 rtp_start_receiving(call->audio.first);
460 rtp_start_receiving(call->video.first); 475 rtp_start_receiving(call->video.first);
461 } else { 476 } else {
462 rc = TOXAV_ERR_CALL_CONTROL_NOT_PAUSED; 477 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
463 goto END; 478 goto END;
464 } 479 }
465 } break; 480 } break;
466 481
467 case TOXAV_CALL_CONTROL_PAUSE: { 482 case TOXAV_CALL_CONTROL_PAUSE: {
468 if (!call->active) {
469 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
470 goto END;
471 }
472
473 /* Only act if not already paused */ 483 /* Only act if not already paused */
474 if (call->msi_call->self_capabilities) { 484 if (call->msi_call->self_capabilities) {
475 call->previous_self_capabilities = call->msi_call->self_capabilities; 485 call->previous_self_capabilities = call->msi_call->self_capabilities;
@@ -484,7 +494,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
484 rtp_stop_receiving(call->audio.first); 494 rtp_stop_receiving(call->audio.first);
485 rtp_stop_receiving(call->video.first); 495 rtp_stop_receiving(call->video.first);
486 } else { 496 } else {
487 rc = TOXAV_ERR_CALL_CONTROL_ALREADY_PAUSED; 497 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
488 goto END; 498 goto END;
489 } 499 }
490 } break; 500 } break;
@@ -498,12 +508,7 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
498 call_remove(call); 508 call_remove(call);
499 } break; 509 } break;
500 510
501 case TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO: { 511 case TOXAV_CALL_CONTROL_MUTE_AUDIO: {
502 if (!call->active) {
503 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
504 goto END;
505 }
506
507 if (call->msi_call->self_capabilities & msi_CapRAudio) { 512 if (call->msi_call->self_capabilities & msi_CapRAudio) {
508 if (msi_change_capabilities(call->msi_call, call-> 513 if (msi_change_capabilities(call->msi_call, call->
509 msi_call->self_capabilities ^ msi_CapRAudio) == -1) { 514 msi_call->self_capabilities ^ msi_CapRAudio) == -1) {
@@ -515,9 +520,13 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
515 520
516 rtp_stop_receiving(call->audio.first); 521 rtp_stop_receiving(call->audio.first);
517 } else { 522 } else {
518 /* This call was already muted so notify the friend that he can 523 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
519 * start sending audio again 524 goto END;
520 */ 525 }
526 } break;
527
528 case TOXAV_CALL_CONTROL_UNMUTE_AUDIO: {
529 if (call->msi_call->self_capabilities ^ msi_CapRAudio) {
521 if (msi_change_capabilities(call->msi_call, call-> 530 if (msi_change_capabilities(call->msi_call, call->
522 msi_call->self_capabilities | msi_CapRAudio) == -1) { 531 msi_call->self_capabilities | msi_CapRAudio) == -1) {
523 /* The only reason for this function to fail is invalid state 532 /* The only reason for this function to fail is invalid state
@@ -527,15 +536,13 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
527 } 536 }
528 537
529 rtp_start_receiving(call->audio.first); 538 rtp_start_receiving(call->audio.first);
539 } else {
540 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
541 goto END;
530 } 542 }
531 } break; 543 } break;
532 544
533 case TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO: { 545 case TOXAV_CALL_CONTROL_HIDE_VIDEO: {
534 if (!call->active) {
535 rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL;
536 goto END;
537 }
538
539 if (call->msi_call->self_capabilities & msi_CapRVideo) { 546 if (call->msi_call->self_capabilities & msi_CapRVideo) {
540 if (msi_change_capabilities(call->msi_call, call-> 547 if (msi_change_capabilities(call->msi_call, call->
541 msi_call->self_capabilities ^ msi_CapRVideo) == -1) { 548 msi_call->self_capabilities ^ msi_CapRVideo) == -1) {
@@ -547,9 +554,13 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
547 554
548 rtp_stop_receiving(call->video.first); 555 rtp_stop_receiving(call->video.first);
549 } else { 556 } else {
550 /* This call was already muted so notify the friend that he can 557 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
551 * start sending video again 558 goto END;
552 */ 559 }
560 } break;
561
562 case TOXAV_CALL_CONTROL_SHOW_VIDEO: {
563 if (call->msi_call->self_capabilities ^ msi_CapRVideo) {
553 if (msi_change_capabilities(call->msi_call, call-> 564 if (msi_change_capabilities(call->msi_call, call->
554 msi_call->self_capabilities | msi_CapRVideo) == -1) { 565 msi_call->self_capabilities | msi_CapRVideo) == -1) {
555 /* The only reason for this function to fail is invalid state 566 /* The only reason for this function to fail is invalid state
@@ -558,7 +569,10 @@ bool toxav_call_control(ToxAV* av, uint32_t friend_number, TOXAV_CALL_CONTROL co
558 goto END; 569 goto END;
559 } 570 }
560 571
561 rtp_start_receiving(call->video.first); 572 rtp_start_receiving(call->audio.first);
573 } else {
574 rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION;
575 goto END;
562 } 576 }
563 } break; 577 } break;
564 } 578 }
@@ -572,26 +586,26 @@ END:
572 return rc == TOXAV_ERR_CALL_CONTROL_OK; 586 return rc == TOXAV_ERR_CALL_CONTROL_OK;
573} 587}
574 588
575void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data) 589void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status_cb* function, void* user_data)
576{ 590{
577 pthread_mutex_lock(av->mutex); 591 pthread_mutex_lock(av->mutex);
578 av->vbcb.first = function; 592 av->abcb.first = function;
579 av->vbcb.second = user_data; 593 av->abcb.second = user_data;
580 pthread_mutex_unlock(av->mutex); 594 pthread_mutex_unlock(av->mutex);
581} 595}
582 596
583bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error) 597bool toxav_audio_bit_rate_set(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE* error)
584{ 598{
585 TOXAV_ERR_BIT_RATE rc = TOXAV_ERR_BIT_RATE_OK; 599 TOXAV_ERR_SET_BIT_RATE rc = TOXAV_ERR_SET_BIT_RATE_OK;
586 ToxAVCall* call; 600 ToxAVCall* call;
587 601
588 if (m_friend_exists(av->m, friend_number) == 0) { 602 if (m_friend_exists(av->m, friend_number) == 0) {
589 rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_FOUND; 603 rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND;
590 goto END; 604 goto END;
591 } 605 }
592 606
593 if (video_bit_rate_invalid(video_bit_rate)) { 607 if (audio_bit_rate_invalid(audio_bit_rate)) {
594 rc = TOXAV_ERR_BIT_RATE_INVALID; 608 rc = TOXAV_ERR_SET_BIT_RATE_INVALID;
595 goto END; 609 goto END;
596 } 610 }
597 611
@@ -599,26 +613,27 @@ bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_
599 call = call_get(av, friend_number); 613 call = call_get(av, friend_number);
600 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { 614 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
601 pthread_mutex_unlock(av->mutex); 615 pthread_mutex_unlock(av->mutex);
602 rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL; 616 rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL;
603 goto END; 617 goto END;
604 } 618 }
605 619
606 if (call->video_bit_rate == video_bit_rate || (call->vba.active && call->vba.bit_rate == video_bit_rate)) { 620 if (call->audio_bit_rate == audio_bit_rate || (call->aba.active && call->aba.bit_rate == audio_bit_rate)) {
607 pthread_mutex_unlock(av->mutex); 621 pthread_mutex_unlock(av->mutex);
608 goto END; 622 goto END;
609 } 623 }
610 624
625
611 pthread_mutex_lock(call->mutex); 626 pthread_mutex_lock(call->mutex);
612 627
613 if (video_bit_rate > call->video_bit_rate && !force) 628 if (audio_bit_rate > call->audio_bit_rate && !force)
614 ba_set(&call->vba, video_bit_rate); 629 ba_set(&call->aba, audio_bit_rate);
615 else { 630 else {
616 /* Cancel any previous non forceful bitrate change request */ 631 /* Cancel any previous non forceful bitrate change request */
617 memset(&call->vba, 0, sizeof(call->vba)); 632 memset(&call->aba, 0, sizeof(call->aba));
618 call->video_bit_rate = video_bit_rate; 633 call->audio_bit_rate = audio_bit_rate;
619 634
620 if (!force && av->vbcb.first) 635 if (!force && av->abcb.first)
621 av->vbcb.first (av, call->friend_number, true, video_bit_rate, av->vbcb.second); 636 av->abcb.first (av, call->friend_number, true, audio_bit_rate, av->abcb.second);
622 } 637 }
623 638
624 pthread_mutex_unlock(call->mutex); 639 pthread_mutex_unlock(call->mutex);
@@ -628,29 +643,29 @@ END:
628 if (error) 643 if (error)
629 *error = rc; 644 *error = rc;
630 645
631 return rc == TOXAV_ERR_BIT_RATE_OK; 646 return rc == TOXAV_ERR_SET_BIT_RATE_OK;
632} 647}
633 648
634void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status_cb* function, void* user_data) 649void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data)
635{ 650{
636 pthread_mutex_lock(av->mutex); 651 pthread_mutex_lock(av->mutex);
637 av->abcb.first = function; 652 av->vbcb.first = function;
638 av->abcb.second = user_data; 653 av->vbcb.second = user_data;
639 pthread_mutex_unlock(av->mutex); 654 pthread_mutex_unlock(av->mutex);
640} 655}
641 656
642bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error) 657bool toxav_video_bit_rate_set(ToxAV* av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE* error)
643{ 658{
644 TOXAV_ERR_BIT_RATE rc = TOXAV_ERR_BIT_RATE_OK; 659 TOXAV_ERR_SET_BIT_RATE rc = TOXAV_ERR_SET_BIT_RATE_OK;
645 ToxAVCall* call; 660 ToxAVCall* call;
646 661
647 if (m_friend_exists(av->m, friend_number) == 0) { 662 if (m_friend_exists(av->m, friend_number) == 0) {
648 rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_FOUND; 663 rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND;
649 goto END; 664 goto END;
650 } 665 }
651 666
652 if (audio_bit_rate_invalid(audio_bit_rate)) { 667 if (video_bit_rate_invalid(video_bit_rate)) {
653 rc = TOXAV_ERR_BIT_RATE_INVALID; 668 rc = TOXAV_ERR_SET_BIT_RATE_INVALID;
654 goto END; 669 goto END;
655 } 670 }
656 671
@@ -658,27 +673,26 @@ bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_
658 call = call_get(av, friend_number); 673 call = call_get(av, friend_number);
659 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { 674 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
660 pthread_mutex_unlock(av->mutex); 675 pthread_mutex_unlock(av->mutex);
661 rc = TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL; 676 rc = TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL;
662 goto END; 677 goto END;
663 } 678 }
664 679
665 if (call->audio_bit_rate == audio_bit_rate || (call->aba.active && call->aba.bit_rate == audio_bit_rate)) { 680 if (call->video_bit_rate == video_bit_rate || (call->vba.active && call->vba.bit_rate == video_bit_rate)) {
666 pthread_mutex_unlock(av->mutex); 681 pthread_mutex_unlock(av->mutex);
667 goto END; 682 goto END;
668 } 683 }
669 684
670
671 pthread_mutex_lock(call->mutex); 685 pthread_mutex_lock(call->mutex);
672 686
673 if (audio_bit_rate > call->audio_bit_rate && !force) 687 if (video_bit_rate > call->video_bit_rate && !force)
674 ba_set(&call->aba, audio_bit_rate); 688 ba_set(&call->vba, video_bit_rate);
675 else { 689 else {
676 /* Cancel any previous non forceful bitrate change request */ 690 /* Cancel any previous non forceful bitrate change request */
677 memset(&call->aba, 0, sizeof(call->aba)); 691 memset(&call->vba, 0, sizeof(call->vba));
678 call->audio_bit_rate = audio_bit_rate; 692 call->video_bit_rate = video_bit_rate;
679 693
680 if (!force && av->abcb.first) 694 if (!force && av->vbcb.first)
681 av->abcb.first (av, call->friend_number, true, audio_bit_rate, av->abcb.second); 695 av->vbcb.first (av, call->friend_number, true, video_bit_rate, av->vbcb.second);
682 } 696 }
683 697
684 pthread_mutex_unlock(call->mutex); 698 pthread_mutex_unlock(call->mutex);
@@ -688,10 +702,112 @@ END:
688 if (error) 702 if (error)
689 *error = rc; 703 *error = rc;
690 704
691 return rc == TOXAV_ERR_BIT_RATE_OK; 705 return rc == TOXAV_ERR_SET_BIT_RATE_OK;
692} 706}
693 707
694bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, TOXAV_ERR_SEND_FRAME* error) 708bool toxav_audio_send_frame(ToxAV* av, uint32_t friend_number, const int16_t* pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME* error)
709{
710 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
711 ToxAVCall* call;
712
713 if (m_friend_exists(av->m, friend_number) == 0) {
714 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
715 goto END;
716 }
717
718 pthread_mutex_lock(av->mutex);
719 call = call_get(av, friend_number);
720 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) {
721 pthread_mutex_unlock(av->mutex);
722 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
723 goto END;
724 }
725
726 pthread_mutex_lock(call->mutex_audio);
727 pthread_mutex_unlock(av->mutex);
728
729 if ( pcm == NULL ) {
730 pthread_mutex_unlock(call->mutex_audio);
731 rc = TOXAV_ERR_SEND_FRAME_NULL;
732 goto END;
733 }
734
735 if ( channels > 2 ) {
736 pthread_mutex_unlock(call->mutex_audio);
737 rc = TOXAV_ERR_SEND_FRAME_INVALID;
738 goto END;
739 }
740
741 { /* Encode and send */
742 if (ac_reconfigure_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
743 pthread_mutex_unlock(call->mutex_audio);
744 rc = TOXAV_ERR_SEND_FRAME_INVALID;
745 goto END;
746 }
747
748 uint8_t dest[sample_count + sizeof(sampling_rate)]; /* This is more than enough always */
749
750 sampling_rate = htonl(sampling_rate);
751 memcpy(dest, &sampling_rate, sizeof(sampling_rate));
752 int vrc = opus_encode(call->audio.second->encoder, pcm, sample_count,
753 dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
754
755 if (vrc < 0) {
756 LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
757 pthread_mutex_unlock(call->mutex_audio);
758 rc = TOXAV_ERR_SEND_FRAME_INVALID;
759 goto END;
760 }
761
762 if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), false) != 0) {
763 LOGGER_WARNING("Failed to send audio packet");
764 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
765 }
766
767
768 /* For bit rate measurement; send dummy packet */
769 if (ba_shoud_send_dummy(&call->aba)) {
770 sampling_rate = ntohl(sampling_rate);
771 if (ac_reconfigure_test_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
772 /* FIXME should the bit rate changing fail here? */
773 pthread_mutex_unlock(call->mutex_audio);
774 rc = TOXAV_ERR_SEND_FRAME_INVALID;
775 goto END;
776 }
777
778 sampling_rate = htonl(sampling_rate);
779 memcpy(dest, &sampling_rate, sizeof(sampling_rate));
780 vrc = opus_encode(call->audio.second->test_encoder, pcm, sample_count,
781 dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
782
783 if (vrc < 0) {
784 LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
785 pthread_mutex_unlock(call->mutex_audio);
786 rc = TOXAV_ERR_SEND_FRAME_INVALID;
787 goto END;
788 }
789
790 if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), true) != 0) {
791 LOGGER_WARNING("Failed to send audio packet");
792 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
793 }
794
795 if (call->aba.end_time == (uint64_t) ~0)
796 call->aba.end_time = current_time_monotonic() + BITRATE_CHANGE_TESTING_TIME_MS;
797 }
798 }
799
800
801 pthread_mutex_unlock(call->mutex_audio);
802
803END:
804 if (error)
805 *error = rc;
806
807 return rc == TOXAV_ERR_SEND_FRAME_OK;
808}
809
810bool toxav_video_send_frame(ToxAV* av, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t* y, const uint8_t* u, const uint8_t* v, const uint8_t* a,TOXAV_ERR_SEND_FRAME* error)
695{ 811{
696 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; 812 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
697 ToxAVCall* call; 813 ToxAVCall* call;
@@ -736,6 +852,10 @@ bool toxav_send_video_frame(ToxAV* av, uint32_t friend_number, uint16_t width, u
736 memcpy(img.planes[VPX_PLANE_U], u, (width/2) * (height/2)); 852 memcpy(img.planes[VPX_PLANE_U], u, (width/2) * (height/2));
737 memcpy(img.planes[VPX_PLANE_V], v, (width/2) * (height/2)); 853 memcpy(img.planes[VPX_PLANE_V], v, (width/2) * (height/2));
738 854
855 /* TODO LOL */
856 if (a && img.planes[VPX_PLANE_ALPHA])
857 memcpy(img.planes[VPX_PLANE_ALPHA], a, width * height);
858
739 int vrc = vpx_codec_encode(call->video.second->encoder, &img, 859 int vrc = vpx_codec_encode(call->video.second->encoder, &img,
740 call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US); 860 call->video.second->frame_counter, 1, 0, MAX_ENCODE_TIME_US);
741 861
@@ -856,109 +976,15 @@ END:
856 return rc == TOXAV_ERR_SEND_FRAME_OK; 976 return rc == TOXAV_ERR_SEND_FRAME_OK;
857} 977}
858 978
859bool toxav_send_audio_frame(ToxAV* av, uint32_t friend_number, const int16_t* pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME* error) 979void toxav_callback_audio_receive_frame(ToxAV* av, toxav_audio_receive_frame_cb* function, void* user_data)
860{ 980{
861 TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK;
862 ToxAVCall* call;
863
864 if (m_friend_exists(av->m, friend_number) == 0) {
865 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND;
866 goto END;
867 }
868
869 pthread_mutex_lock(av->mutex); 981 pthread_mutex_lock(av->mutex);
870 call = call_get(av, friend_number); 982 av->acb.first = function;
871 if (call == NULL || !call->active || call->msi_call->state != msi_CallActive) { 983 av->acb.second = user_data;
872 pthread_mutex_unlock(av->mutex);
873 rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL;
874 goto END;
875 }
876
877 pthread_mutex_lock(call->mutex_audio);
878 pthread_mutex_unlock(av->mutex); 984 pthread_mutex_unlock(av->mutex);
879
880 if ( pcm == NULL ) {
881 pthread_mutex_unlock(call->mutex_audio);
882 rc = TOXAV_ERR_SEND_FRAME_NULL;
883 goto END;
884 }
885
886 if ( channels > 2 ) {
887 pthread_mutex_unlock(call->mutex_audio);
888 rc = TOXAV_ERR_SEND_FRAME_INVALID;
889 goto END;
890 }
891
892 { /* Encode and send */
893 if (ac_reconfigure_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
894 pthread_mutex_unlock(call->mutex_audio);
895 rc = TOXAV_ERR_SEND_FRAME_INVALID;
896 goto END;
897 }
898
899 uint8_t dest[sample_count + sizeof(sampling_rate)]; /* This is more than enough always */
900
901 sampling_rate = htonl(sampling_rate);
902 memcpy(dest, &sampling_rate, sizeof(sampling_rate));
903 int vrc = opus_encode(call->audio.second->encoder, pcm, sample_count,
904 dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
905
906 if (vrc < 0) {
907 LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
908 pthread_mutex_unlock(call->mutex_audio);
909 rc = TOXAV_ERR_SEND_FRAME_INVALID;
910 goto END;
911 }
912
913 if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), false) != 0) {
914 LOGGER_WARNING("Failed to send audio packet");
915 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
916 }
917
918
919 /* For bit rate measurement; send dummy packet */
920 if (ba_shoud_send_dummy(&call->aba)) {
921 sampling_rate = ntohl(sampling_rate);
922 if (ac_reconfigure_test_encoder(call->audio.second, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) {
923 /* FIXME should the bit rate changing fail here? */
924 pthread_mutex_unlock(call->mutex_audio);
925 rc = TOXAV_ERR_SEND_FRAME_INVALID;
926 goto END;
927 }
928
929 sampling_rate = htonl(sampling_rate);
930 memcpy(dest, &sampling_rate, sizeof(sampling_rate));
931 vrc = opus_encode(call->audio.second->test_encoder, pcm, sample_count,
932 dest + sizeof(sampling_rate), sizeof(dest) - sizeof(sampling_rate));
933
934 if (vrc < 0) {
935 LOGGER_WARNING("Failed to encode frame %s", opus_strerror(vrc));
936 pthread_mutex_unlock(call->mutex_audio);
937 rc = TOXAV_ERR_SEND_FRAME_INVALID;
938 goto END;
939 }
940
941 if (rtp_send_data(call->audio.first, dest, vrc + sizeof(sampling_rate), true) != 0) {
942 LOGGER_WARNING("Failed to send audio packet");
943 rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED;
944 }
945
946 if (call->aba.end_time == (uint64_t) ~0)
947 call->aba.end_time = current_time_monotonic() + BITRATE_CHANGE_TESTING_TIME_MS;
948 }
949 }
950
951
952 pthread_mutex_unlock(call->mutex_audio);
953
954END:
955 if (error)
956 *error = rc;
957
958 return rc == TOXAV_ERR_SEND_FRAME_OK;
959} 985}
960 986
961void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data) 987void toxav_callback_video_receive_frame(ToxAV* av, toxav_video_receive_frame_cb* function, void* user_data)
962{ 988{
963 pthread_mutex_lock(av->mutex); 989 pthread_mutex_lock(av->mutex);
964 av->vcb.first = function; 990 av->vcb.first = function;
@@ -966,14 +992,6 @@ void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb*
966 pthread_mutex_unlock(av->mutex); 992 pthread_mutex_unlock(av->mutex);
967} 993}
968 994
969void toxav_callback_receive_audio_frame(ToxAV* av, toxav_receive_audio_frame_cb* function, void* user_data)
970{
971 pthread_mutex_lock(av->mutex);
972 av->acb.first = function;
973 av->acb.second = user_data;
974 pthread_mutex_unlock(av->mutex);
975}
976
977 995
978/******************************************************************************* 996/*******************************************************************************
979 * 997 *
diff --git a/toxav/toxav.h b/toxav/toxav.h
index b0e7e37d..c75f8bff 100644
--- a/toxav/toxav.h
+++ b/toxav/toxav.h
@@ -1,22 +1,22 @@
1/** toxav.h 1/* toxav.h
2 * 2 *
3 * Copyright (C) 2013-2015 Tox project All Rights Reserved. 3 * Copyright (C) 2013-2015 Tox project All Rights Reserved.
4 * 4 *
5 * This file is part of Tox. 5 * This file is part of Tox.
6 * 6 *
7 * Tox is free software: you can redistribute it and/or modify 7 * Tox is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or 9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version. 10 * (at your option) any later version.
11 * 11 *
12 * Tox is distributed in the hope that it will be useful, 12 * Tox is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 * 16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */ 20 */
21 21
22#ifndef TOXAV_H 22#ifndef TOXAV_H
@@ -29,45 +29,175 @@
29#ifdef __cplusplus 29#ifdef __cplusplus
30extern "C" { 30extern "C" {
31#endif 31#endif
32
32/** \page av Public audio/video API for Tox clients. 33/** \page av Public audio/video API for Tox clients.
33 * 34 *
35 * This API can handle multiple calls. Each call has its state, in very rare
36 * occasions the library can change the state of the call without apps knowledge.
37 *
38 */
39/** \subsection events Events and callbacks
40 *
41 * As in Core API, events are handled by callbacks. One callback can be
42 * registered per event. All events have a callback function type named
43 * `toxav_{event}_cb` and a function to register it named `tox_callback_{event}`.
44 * Passing a NULL callback will result in no callback being registered for that
45 * event. Only one callback per event can be registered, so if a client needs
46 * multiple event listeners, it needs to implement the dispatch functionality
47 * itself. Unlike Core API, lack of some event handlers will cause the the
48 * library to drop calls before they are started. Hanging up call from a
49 * callback causes undefined behaviour.
50 *
51 */
52/** \subsection threading Threading implications
53 *
34 * Unlike the Core API, this API is fully thread-safe. The library will ensure 54 * Unlike the Core API, this API is fully thread-safe. The library will ensure
35 * the proper synchronisation of parallel calls. 55 * the proper synchronisation of parallel calls.
56 *
57 * A common way to run ToxAV (multiple or single instance) is to have a thread,
58 * separate from tox instance thread, running a simple toxav_iterate loop,
59 * sleeping for toxav_iteration_interval * milliseconds on each iteration.
60 *
36 */ 61 */
37/** 62/**
38 * The type of the Tox Audio/Video subsystem object. 63 * External Tox type.
39 */ 64 */
40typedef struct ToxAV ToxAV;
41#ifndef TOX_DEFINED 65#ifndef TOX_DEFINED
42#define TOX_DEFINED 66#define TOX_DEFINED
67typedef struct Tox Tox;
68#endif /* TOX_DEFINED */
69
43/** 70/**
44 * The type of a Tox instance. Repeated here so this file does not have a direct 71 * ToxAV.
45 * dependency on the Core interface.
46 */ 72 */
47typedef struct Tox Tox; 73/**
48#endif 74 * The ToxAV instance type. Each ToxAV instance can be bound to only one Tox
75 * instance, and Tox instance can have only one ToxAV instance. One must make
76 * sure to close ToxAV instance prior closing Tox instance otherwise undefined
77 * behaviour occurs. Upon closing of ToxAV instance, all active calls will be
78 * forcibly terminated without notifying peers.
79 *
80 */
81#ifndef TOXAV_DEFINED
82#define TOXAV_DEFINED
83typedef struct ToxAV ToxAV;
84#endif /* TOXAV_DEFINED */
85
86
87/*******************************************************************************
88 *
89 * :: API version
90 *
91 ******************************************************************************/
92
93
94
95/**
96 * The major version number. Incremented when the API or ABI changes in an
97 * incompatible way.
98 */
99#define TOXAV_VERSION_MAJOR 0u
100
101/**
102 * The minor version number. Incremented when functionality is added without
103 * breaking the API or ABI. Set to 0 when the major version number is
104 * incremented.
105 */
106#define TOXAV_VERSION_MINOR 0u
107
108/**
109 * The patch or revision number. Incremented when bugfixes are applied without
110 * changing any functionality or API or ABI.
111 */
112#define TOXAV_VERSION_PATCH 0u
113
114/**
115 * A macro to check at preprocessing time whether the client code is compatible
116 * with the installed version of ToxAV.
117 */
118#define TOXAV_VERSION_IS_API_COMPATIBLE(MAJOR, MINOR, PATCH) \
119 (TOXAV_VERSION_MAJOR == MAJOR && \
120 (TOXAV_VERSION_MINOR > MINOR || \
121 (TOXAV_VERSION_MINOR == MINOR && \
122 TOXAV_VERSION_PATCH >= PATCH)))
123
124/**
125 * A macro to make compilation fail if the client code is not compatible with
126 * the installed version of ToxAV.
127 */
128#define TOXAV_VERSION_REQUIRE(MAJOR, MINOR, PATCH) \
129 typedef char toxav_required_version[TOXAV_IS_COMPATIBLE(MAJOR, MINOR, PATCH) ? 1 : -1]
130
131/**
132 * A convenience macro to call toxav_version_is_compatible with the currently
133 * compiling API version.
134 */
135#define TOXAV_VERSION_IS_ABI_COMPATIBLE() \
136 toxav_version_is_compatible(TOXAV_VERSION_MAJOR, TOXAV_VERSION_MINOR, TOXAV_VERSION_PATCH)
137
138/**
139 * Return the major version number of the library. Can be used to display the
140 * ToxAV library version or to check whether the client is compatible with the
141 * dynamically linked version of ToxAV.
142 */
143uint32_t toxav_version_major(void);
144
145/**
146 * Return the minor version number of the library.
147 */
148uint32_t toxav_version_minor(void);
149
150/**
151 * Return the patch number of the library.
152 */
153uint32_t toxav_version_patch(void);
154
155/**
156 * Return whether the compiled library version is compatible with the passed
157 * version numbers.
158 */
159bool toxav_version_is_compatible(uint32_t major, uint32_t minor, uint32_t patch);
160
161
49/******************************************************************************* 162/*******************************************************************************
50 * 163 *
51 * :: Creation and destruction 164 * :: Creation and destruction
52 * 165 *
53 ******************************************************************************/ 166 ******************************************************************************/
167
168
169
54typedef enum TOXAV_ERR_NEW { 170typedef enum TOXAV_ERR_NEW {
55 TOXAV_ERR_NEW_OK, 171
56 TOXAV_ERR_NEW_NULL, 172 /**
57 /** 173 * The function returned successfully.
58 * Memory allocation failure while trying to allocate structures required for 174 */
59 * the A/V session. 175 TOXAV_ERR_NEW_OK,
60 */ 176
61 TOXAV_ERR_NEW_MALLOC, 177 /**
62 /** 178 * One of the arguments to the function was NULL when it was not expected.
63 * Attempted to create a second session for the same Tox instance. 179 */
64 */ 180 TOXAV_ERR_NEW_NULL,
65 TOXAV_ERR_NEW_MULTIPLE 181
182 /**
183 * Memory allocation failure while trying to allocate structures required for
184 * the A/V session.
185 */
186 TOXAV_ERR_NEW_MALLOC,
187
188 /**
189 * Attempted to create a second session for the same Tox instance.
190 */
191 TOXAV_ERR_NEW_MULTIPLE,
192
66} TOXAV_ERR_NEW; 193} TOXAV_ERR_NEW;
194
195
67/** 196/**
68 * Start new A/V session. There can only be only one session per Tox instance. 197 * Start new A/V session. There can only be only one session per Tox instance.
69 */ 198 */
70ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error); 199ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error);
200
71/** 201/**
72 * Releases all resources associated with the A/V session. 202 * Releases all resources associated with the A/V session.
73 * 203 *
@@ -75,62 +205,86 @@ ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error);
75 * notifying peers. After calling this function, no other functions may be 205 * notifying peers. After calling this function, no other functions may be
76 * called and the av pointer becomes invalid. 206 * called and the av pointer becomes invalid.
77 */ 207 */
78void toxav_kill(ToxAV *av); 208void toxav_kill(ToxAV *toxAV);
209
79/** 210/**
80 * Returns the Tox instance the A/V object was created for. 211 * Returns the Tox instance the A/V object was created for.
81 */ 212 */
82Tox *toxav_get_tox(ToxAV *av); 213Tox *toxav_get_tox(const ToxAV *toxAV);
214
215
83/******************************************************************************* 216/*******************************************************************************
84 * 217 *
85 * :: A/V event loop 218 * :: A/V event loop
86 * 219 *
87 ******************************************************************************/ 220 ******************************************************************************/
221
222
223
88/** 224/**
89 * Returns the interval in milliseconds when the next toxav_iterate call should 225 * Returns the interval in milliseconds when the next toxav_iterate call should
90 * be. If no call is active at the moment, this function returns 200. 226 * be. If no call is active at the moment, this function returns 200.
91 */ 227 */
92uint32_t toxav_iteration_interval(ToxAV const *av); 228uint32_t toxav_iteration_interval(const ToxAV *toxAV);
229
93/** 230/**
94 * Main loop for the session. This function needs to be called in intervals of 231 * Main loop for the session. This function needs to be called in intervals of
95 * toxav_iteration_interval() milliseconds. It is best called in the separate 232 * toxav_iteration_interval() milliseconds. It is best called in the separate
96 * thread from tox_iterate. 233 * thread from tox_iterate.
97 */ 234 */
98void toxav_iterate(ToxAV *av); 235void toxav_iterate(ToxAV *toxAV);
236
237
99/******************************************************************************* 238/*******************************************************************************
100 * 239 *
101 * :: Call setup 240 * :: Call setup
102 * 241 *
103 ******************************************************************************/ 242 ******************************************************************************/
243
244
245
104typedef enum TOXAV_ERR_CALL { 246typedef enum TOXAV_ERR_CALL {
105 TOXAV_ERR_CALL_OK, 247
106 /** 248 /**
107 * A resource allocation error occurred while trying to create the structures 249 * The function returned successfully.
108 * required for the call. 250 */
109 */ 251 TOXAV_ERR_CALL_OK,
110 TOXAV_ERR_CALL_MALLOC, 252
111 /** 253 /**
112 * The friend number did not designate a valid friend. 254 * A resource allocation error occurred while trying to create the structures
113 */ 255 * required for the call.
114 TOXAV_ERR_CALL_FRIEND_NOT_FOUND, 256 */
115 /** 257 TOXAV_ERR_CALL_MALLOC,
116 * The friend was valid, but not currently connected. 258
117 */ 259 /**
118 TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED, 260 * The friend number did not designate a valid friend.
119 /** 261 */
120 * Attempted to call a friend while already in an audio or video call with 262 TOXAV_ERR_CALL_FRIEND_NOT_FOUND,
121 * them. 263
122 */ 264 /**
123 TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL, 265 * The friend was valid, but not currently connected.
124 /** 266 */
125 * Audio or video bit rate is invalid. 267 TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED,
126 */ 268
127 TOXAV_ERR_CALL_INVALID_BIT_RATE 269 /**
270 * Attempted to call a friend while already in an audio or video call with
271 * them.
272 */
273 TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL,
274
275 /**
276 * Audio or video bit rate is invalid.
277 */
278 TOXAV_ERR_CALL_INVALID_BIT_RATE,
279
128} TOXAV_ERR_CALL; 280} TOXAV_ERR_CALL;
281
282
129/** 283/**
130 * Call a friend. This will start ringing the friend. 284 * Call a friend. This will start ringing the friend.
131 * 285 *
132 * It is the client's responsibility to stop ringing after a certain timeout, 286 * It is the client's responsibility to stop ringing after a certain timeout,
133 * if such behaviour is desired. If the client does not stop ringing, the A/V 287 * if such behaviour is desired. If the client does not stop ringing, the
134 * library will not stop until the friend is disconnected. 288 * library will not stop until the friend is disconnected.
135 * 289 *
136 * @param friend_number The friend number of the friend that should be called. 290 * @param friend_number The friend number of the friend that should be called.
@@ -139,39 +293,57 @@ typedef enum TOXAV_ERR_CALL {
139 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable 293 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable
140 * video sending. 294 * video sending.
141 */ 295 */
142bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error); 296bool toxav_call(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error);
297
143/** 298/**
144 * The function type for the `call` callback. 299 * The function type for the call callback.
300 *
301 * @param friend_number The friend number from which the call is incoming.
302 * @param audio_enabled True if friend is sending audio.
303 * @param video_enabled True if friend is sending video.
145 */ 304 */
146typedef void toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data); 305typedef void toxav_call_cb(ToxAV *toxAV, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data);
306
307
147/** 308/**
148 * Set the callback for the `call` event. Pass NULL to unset. 309 * Set the callback for the `call` event. Pass NULL to unset.
149 * 310 *
150 * This event is triggered when a call is received from a friend.
151 */ 311 */
152void toxav_callback_call(ToxAV *av, toxav_call_cb *function, void *user_data); 312void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data);
313
153typedef enum TOXAV_ERR_ANSWER { 314typedef enum TOXAV_ERR_ANSWER {
154 TOXAV_ERR_ANSWER_OK, 315
155 /** 316 /**
156 * Failed to initialize codecs for call session. Note that codec initiation 317 * The function returned successfully.
157 * will fail if there is no receive callback registered for either audio or 318 */
158 * video. 319 TOXAV_ERR_ANSWER_OK,
159 */ 320
160 TOXAV_ERR_ANSWER_CODEC_INITIALIZATION, 321 /**
161 /** 322 * Failed to initialize codecs for call session. Note that codec initiation
162 * The friend number did not designate a valid friend. 323 * will fail if there is no receive callback registered for either audio or
163 */ 324 * video.
164 TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND, 325 */
165 /** 326 TOXAV_ERR_ANSWER_CODEC_INITIALIZATION,
166 * The friend was valid, but they are not currently trying to initiate a call. 327
167 * This is also returned if this client is already in a call with the friend. 328 /**
168 */ 329 * The friend number did not designate a valid friend.
169 TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING, 330 */
170 /** 331 TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND,
171 * Audio or video bit rate is invalid. 332
172 */ 333 /**
173 TOXAV_ERR_ANSWER_INVALID_BIT_RATE 334 * The friend was valid, but they are not currently trying to initiate a call.
335 * This is also returned if this client is already in a call with the friend.
336 */
337 TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING,
338
339 /**
340 * Audio or video bit rate is invalid.
341 */
342 TOXAV_ERR_ANSWER_INVALID_BIT_RATE,
343
174} TOXAV_ERR_ANSWER; 344} TOXAV_ERR_ANSWER;
345
346
175/** 347/**
176 * Accept an incoming call. 348 * Accept an incoming call.
177 * 349 *
@@ -184,113 +356,155 @@ typedef enum TOXAV_ERR_ANSWER {
184 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable 356 * @param video_bit_rate Video bit rate in Kb/sec. Set this to 0 to disable
185 * video sending. 357 * video sending.
186 */ 358 */
187bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error); 359bool toxav_answer(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error);
360
361
188/******************************************************************************* 362/*******************************************************************************
189 * 363 *
190 * :: Call state graph 364 * :: Call state graph
191 * 365 *
192 ******************************************************************************/ 366 ******************************************************************************/
367
368
369
193enum TOXAV_CALL_STATE { 370enum TOXAV_CALL_STATE {
194 /** 371
195 * The flag that marks that friend is sending audio. 372 /**
196 */ 373 * Set by the AV core if an error occurred on the remote end or if friend
197 TOXAV_CALL_STATE_SENDING_A = 1, 374 * timed out. This is the final state after which no more state
198 /** 375 * transitions can occur for the call. This call state will never be triggered
199 * The flag that marks that friend is sending video. 376 * in combination with other call states.
200 */ 377 */
201 TOXAV_CALL_STATE_SENDING_V = 2, 378 TOXAV_CALL_STATE_ERROR = 1,
202 /** 379
203 * The flag that marks that friend is receiving audio. 380 /**
204 */ 381 * The call has finished. This is the final state after which no more state
205 TOXAV_CALL_STATE_RECEIVING_A = 4, 382 * transitions can occur for the call. This call state will never be
206 /** 383 * triggered in combination with other call states.
207 * The flag that marks that friend is receiving video. 384 */
208 */ 385 TOXAV_CALL_STATE_FINISHED = 2,
209 TOXAV_CALL_STATE_RECEIVING_V = 8, 386
210 /** 387 /**
211 * The call has finished. This is the final state after which no more state 388 * The flag that marks that friend is sending audio.
212 * transitions can occur for the call. This call state will never be 389 */
213 * triggered in combination with other call states. 390 TOXAV_CALL_STATE_SENDING_A = 4,
214 */ 391
215 TOXAV_CALL_STATE_FINISHED = 16, 392 /**
216 /** 393 * The flag that marks that friend is sending video.
217 * Set by the AV core if an error occurred on the remote end. This call 394 */
218 * state will never be triggered in combination with other call states. 395 TOXAV_CALL_STATE_SENDING_V = 8,
219 */ 396
220 TOXAV_CALL_STATE_ERROR = 32768 397 /**
398 * The flag that marks that friend is receiving audio.
399 */
400 TOXAV_CALL_STATE_RECEIVING_A = 16,
401
402 /**
403 * The flag that marks that friend is receiving video.
404 */
405 TOXAV_CALL_STATE_RECEIVING_V = 32,
406
221}; 407};
408
409
222/** 410/**
223 * The function type for the `call_state` callback. 411 * The function type for the call_state callback.
224 * 412 *
225 * @param friend_number The friend number for which the call state changed. 413 * @param friend_number The friend number for which the call state changed.
226 * @param state The new call state. 414 * @param state The new call state which is guaranteed to be different than
415 * the previous state. The state is set to 0 when the call is paused.
227 */ 416 */
228typedef void toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data); 417typedef void toxav_call_state_cb(ToxAV *toxAV, uint32_t friend_number, uint32_t state, void *user_data);
418
419
229/** 420/**
230 * Set the callback for the `call_state` event. Pass NULL to unset. 421 * Set the callback for the `call_state` event. Pass NULL to unset.
231 * 422 *
232 * This event is triggered when a call state transition occurs.
233 */ 423 */
234void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *function, void *user_data); 424void toxav_callback_call_state(ToxAV *toxAV, toxav_call_state_cb *callback, void *user_data);
425
426
235/******************************************************************************* 427/*******************************************************************************
236 * 428 *
237 * :: Call control 429 * :: Call control
238 * 430 *
239 ******************************************************************************/ 431 ******************************************************************************/
432
433
434
240typedef enum TOXAV_CALL_CONTROL { 435typedef enum TOXAV_CALL_CONTROL {
241 /** 436
242 * Resume a previously paused call. Only valid if the pause was caused by this 437 /**
243 * client, if not, this control is ignored. Not valid before the call is accepted. 438 * Resume a previously paused call. Only valid if the pause was caused by this
244 */ 439 * client, if not, this control is ignored. Not valid before the call is accepted.
245 TOXAV_CALL_CONTROL_RESUME, 440 */
246 /** 441 TOXAV_CALL_CONTROL_RESUME,
247 * Put a call on hold. Not valid before the call is accepted. 442
248 */ 443 /**
249 TOXAV_CALL_CONTROL_PAUSE, 444 * Put a call on hold. Not valid before the call is accepted.
250 /** 445 */
251 * Reject a call if it was not answered, yet. Cancel a call after it was 446 TOXAV_CALL_CONTROL_PAUSE,
252 * answered. 447
253 */ 448 /**
254 TOXAV_CALL_CONTROL_CANCEL, 449 * Reject a call if it was not answered, yet. Cancel a call after it was
255 /** 450 * answered.
256 * Request that the friend stops sending audio. Regardless of the friend's 451 */
257 * compliance, this will cause the `receive_audio_frame` event to stop being 452 TOXAV_CALL_CONTROL_CANCEL,
258 * triggered on receiving an audio frame from the friend. If the audio was 453
259 * already muted, calling this control will notify client to start sending 454 /**
260 * audio again. 455 * Request that the friend stops sending audio. Regardless of the friend's
261 */ 456 * compliance, this will cause the audio_receive_frame event to stop being
262 TOXAV_CALL_CONTROL_TOGGLE_MUTE_AUDIO, 457 * triggered on receiving an audio frame from the friend.
263 /** 458 */
264 * Request that the friend stops sending video. Regardless of the friend's 459 TOXAV_CALL_CONTROL_MUTE_AUDIO,
265 * compliance, this will cause the `receive_video_frame` event to stop being 460
266 * triggered on receiving an video frame from the friend. If the video was 461 /**
267 * already hidden, calling this control will notify client to start sending 462 * Calling this control will notify client to start sending audio again.
268 * video again. 463 */
269 */ 464 TOXAV_CALL_CONTROL_UNMUTE_AUDIO,
270 TOXAV_CALL_CONTROL_TOGGLE_HIDE_VIDEO 465
466 /**
467 * Request that the friend stops sending video. Regardless of the friend's
468 * compliance, this will cause the video_receive_frame event to stop being
469 * triggered on receiving an video frame from the friend.
470 */
471 TOXAV_CALL_CONTROL_HIDE_VIDEO,
472
473 /**
474 * Calling this control will notify client to start sending video again.
475 */
476 TOXAV_CALL_CONTROL_SHOW_VIDEO,
477
271} TOXAV_CALL_CONTROL; 478} TOXAV_CALL_CONTROL;
479
480
272typedef enum TOXAV_ERR_CALL_CONTROL { 481typedef enum TOXAV_ERR_CALL_CONTROL {
273 TOXAV_ERR_CALL_CONTROL_OK, 482
274 /** 483 /**
275 * The friend_number passed did not designate a valid friend. 484 * The function returned successfully.
276 */ 485 */
277 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND, 486 TOXAV_ERR_CALL_CONTROL_OK,
278 /** 487
279 * This client is currently not in a call with the friend. Before the call is 488 /**
280 * answered, only CANCEL is a valid control. 489 * The friend_number passed did not designate a valid friend.
281 */ 490 */
282 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL, 491 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND,
283 /** 492
284 * Attempted to resume a call that was not paused. 493 /**
285 */ 494 * This client is currently not in a call with the friend. Before the call is
286 TOXAV_ERR_CALL_CONTROL_NOT_PAUSED, 495 * answered, only CANCEL is a valid control.
287 /** 496 */
288 * The call was already paused on this client. It is valid to pause if the 497 TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL,
289 * other party paused the call. The call will resume after both parties sent 498
290 * the RESUME control. 499 /**
291 */ 500 * Happens if user tried to pause an already paused call or if trying to
292 TOXAV_ERR_CALL_CONTROL_ALREADY_PAUSED 501 * resume a call that is not paused.
502 */
503 TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION,
504
293} TOXAV_ERR_CALL_CONTROL; 505} TOXAV_ERR_CALL_CONTROL;
506
507
294/** 508/**
295 * Sends a call control command to a friend. 509 * Sends a call control command to a friend.
296 * 510 *
@@ -300,29 +514,44 @@ typedef enum TOXAV_ERR_CALL_CONTROL {
300 * 514 *
301 * @return true on success. 515 * @return true on success.
302 */ 516 */
303bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error); 517bool toxav_call_control(ToxAV *toxAV, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error);
518
519
304/******************************************************************************* 520/*******************************************************************************
305 * 521 *
306 * :: Controlling bit rates 522 * :: Controlling bit rates
307 * 523 *
308 ******************************************************************************/ 524 ******************************************************************************/
309typedef enum TOXAV_ERR_BIT_RATE { 525
310 TOXAV_ERR_BIT_RATE_OK, 526
311 /** 527
312 * The bit rate passed was not one of the supported values. 528typedef enum TOXAV_ERR_SET_BIT_RATE {
313 */ 529
314 TOXAV_ERR_BIT_RATE_INVALID, 530 /**
315 /** 531 * The function returned successfully.
316 * The friend_number passed did not designate a valid friend. 532 */
317 */ 533 TOXAV_ERR_SET_BIT_RATE_OK,
318 TOXAV_ERR_BIT_RATE_FRIEND_NOT_FOUND, 534
319 /** 535 /**
320 * This client is currently not in a call with the friend. 536 * The bit rate passed was not one of the supported values.
321 */ 537 */
322 TOXAV_ERR_BIT_RATE_FRIEND_NOT_IN_CALL 538 TOXAV_ERR_SET_BIT_RATE_INVALID,
323} TOXAV_ERR_BIT_RATE; 539
324/** 540 /**
325 * The function type for the `audio_bit_rate_status` callback. 541 * The friend_number passed did not designate a valid friend.
542 */
543 TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_FOUND,
544
545 /**
546 * This client is currently not in a call with the friend.
547 */
548 TOXAV_ERR_SET_BIT_RATE_FRIEND_NOT_IN_CALL,
549
550} TOXAV_ERR_SET_BIT_RATE;
551
552
553/**
554 * The function type for the audio_bit_rate_status callback.
326 * 555 *
327 * @param friend_number The friend number of the friend for which to set the 556 * @param friend_number The friend number of the friend for which to set the
328 * audio bit rate. 557 * audio bit rate.
@@ -334,11 +563,15 @@ typedef enum TOXAV_ERR_BIT_RATE {
334 * or the non forceful change failed. 563 * or the non forceful change failed.
335 * @param bit_rate The bit rate in Kb/sec. 564 * @param bit_rate The bit rate in Kb/sec.
336 */ 565 */
337typedef void toxav_audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); 566typedef void toxav_audio_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data);
567
568
338/** 569/**
339 * Set the callback for the `audio_bit_rate_status` event. Pass NULL to unset. 570 * Set the callback for the `audio_bit_rate_status` event. Pass NULL to unset.
571 *
340 */ 572 */
341void toxav_callback_audio_bit_rate_status(ToxAV *av, toxav_audio_bit_rate_status_cb *function, void *user_data); 573void toxav_callback_audio_bit_rate_status(ToxAV *toxAV, toxav_audio_bit_rate_status_cb *callback, void *user_data);
574
342/** 575/**
343 * Set the audio bit rate to be used in subsequent audio frames. If the passed 576 * Set the audio bit rate to be used in subsequent audio frames. If the passed
344 * bit rate is the same as the current bit rate this function will return true 577 * bit rate is the same as the current bit rate this function will return true
@@ -351,12 +584,13 @@ void toxav_callback_audio_bit_rate_status(ToxAV *av, toxav_audio_bit_rate_status
351 * audio bit rate. 584 * audio bit rate.
352 * @param audio_bit_rate The new audio bit rate in Kb/sec. Set to 0 to disable 585 * @param audio_bit_rate The new audio bit rate in Kb/sec. Set to 0 to disable
353 * audio sending. 586 * audio sending.
354 * 587 * @param force True if the bit rate change is forceful.
355 * @see toxav_call for the valid bit rates. 588 *
356 */ 589 */
357bool toxav_set_audio_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); 590bool toxav_audio_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE *error);
591
358/** 592/**
359 * The function type for the `video_bit_rate_status` callback. 593 * The function type for the video_bit_rate_status callback.
360 * 594 *
361 * @param friend_number The friend number of the friend for which to set the 595 * @param friend_number The friend number of the friend for which to set the
362 * video bit rate. 596 * video bit rate.
@@ -368,79 +602,78 @@ bool toxav_set_audio_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_
368 * or the non forceful change failed. 602 * or the non forceful change failed.
369 * @param bit_rate The bit rate in Kb/sec. 603 * @param bit_rate The bit rate in Kb/sec.
370 */ 604 */
371typedef void toxav_video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); 605typedef void toxav_video_bit_rate_status_cb(ToxAV *toxAV, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data);
606
607
372/** 608/**
373 * Set the callback for the `video_bit_rate_status` event. Pass NULL to unset. 609 * Set the callback for the `video_bit_rate_status` event. Pass NULL to unset.
610 *
374 */ 611 */
375void toxav_callback_video_bit_rate_status(ToxAV *av, toxav_video_bit_rate_status_cb *function, void *user_data); 612void toxav_callback_video_bit_rate_status(ToxAV *toxAV, toxav_video_bit_rate_status_cb *callback, void *user_data);
613
376/** 614/**
377 * Set the video bit rate to be used in subsequent video frames. If the passed 615 * Set the video bit rate to be used in subsequent video frames. If the passed
378 * bit rate is the same as the current bit rate this function will return true 616 * bit rate is the same as the current bit rate this function will return true
379 * without calling a callback. If there is an active non forceful setup with the 617 * without calling a callback. If there is an active non forceful setup with the
380 * passed bit rate and the new set request is forceful, the bit rate is 618 * passed video bit rate and the new set request is forceful, the bit rate is
381 * forcefully set and the previous non forceful request is cancelled. The active 619 * forcefully set and the previous non forceful request is cancelled. The active
382 * non forceful setup will be canceled in favour of new non forceful setup. 620 * non forceful setup will be canceled in favour of new non forceful setup.
383 * 621 *
384 * @param friend_number The friend number of the friend for which to set the 622 * @param friend_number The friend number of the friend for which to set the
385 * video bit rate. 623 * video bit rate.
386 * @param video_bit_rate The new video bit rate in Kb/sec. Set to 0 to disable 624 * @param audio_bit_rate The new video bit rate in Kb/sec. Set to 0 to disable
387 * video sending. 625 * video sending.
388 * 626 * @param force True if the bit rate change is forceful.
389 * @see toxav_call for the valid bit rates. 627 *
390 */ 628 */
391bool toxav_set_video_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); 629bool toxav_video_bit_rate_set(ToxAV *toxAV, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_SET_BIT_RATE *error);
630
631
392/******************************************************************************* 632/*******************************************************************************
393 * 633 *
394 * :: A/V sending 634 * :: A/V sending
395 * 635 *
396 ******************************************************************************/ 636 ******************************************************************************/
397/** 637
398 * Common error codes for the send_*_frame functions. 638
399 */ 639
400typedef enum TOXAV_ERR_SEND_FRAME { 640typedef enum TOXAV_ERR_SEND_FRAME {
401 TOXAV_ERR_SEND_FRAME_OK, 641
402 /** 642 /**
403 * In case of video, one of Y, U, or V was NULL. In case of audio, the samples 643 * The function returned successfully.
404 * data pointer was NULL. 644 */
405 */ 645 TOXAV_ERR_SEND_FRAME_OK,
406 TOXAV_ERR_SEND_FRAME_NULL, 646
407 /** 647 /**
408 * The friend_number passed did not designate a valid friend. 648 * In case of video, one of Y, U, or V was NULL. In case of audio, the samples
409 */ 649 * data pointer was NULL.
410 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND, 650 */
411 /** 651 TOXAV_ERR_SEND_FRAME_NULL,
412 * This client is currently not in a call with the friend. 652
413 */ 653 /**
414 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL, 654 * The friend_number passed did not designate a valid friend.
415 /** 655 */
416 * One of the frame parameters was invalid. E.g. the resolution may be too 656 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND,
417 * small or too large, or the audio sampling rate may be unsupported. 657
418 */ 658 /**
419 TOXAV_ERR_SEND_FRAME_INVALID, 659 * This client is currently not in a call with the friend.
420 /** 660 */
421 * Failed to push frame through rtp interface. 661 TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL,
422 */ 662
423 TOXAV_ERR_SEND_FRAME_RTP_FAILED 663 /**
664 * One of the frame parameters was invalid. E.g. the resolution may be too
665 * small or too large, or the audio sampling rate may be unsupported.
666 */
667 TOXAV_ERR_SEND_FRAME_INVALID,
668
669 /**
670 * Failed to push frame through rtp interface.
671 */
672 TOXAV_ERR_SEND_FRAME_RTP_FAILED,
673
424} TOXAV_ERR_SEND_FRAME; 674} TOXAV_ERR_SEND_FRAME;
425/** 675
426 * Send a video frame to a friend. 676
427 *
428 * Y - plane should be of size: height * width
429 * U - plane should be of size: (height/2) * (width/2)
430 * V - plane should be of size: (height/2) * (width/2)
431 *
432 * @param friend_number The friend number of the friend to which to send a video
433 * frame.
434 * @param width Width of the frame in pixels.
435 * @param height Height of the frame in pixels.
436 * @param y Y (Luminance) plane data.
437 * @param u U (Chroma) plane data.
438 * @param v V (Chroma) plane data.
439 */
440bool toxav_send_video_frame(ToxAV *av, uint32_t friend_number,
441 uint16_t width, uint16_t height,
442 uint8_t const *y, uint8_t const *u, uint8_t const *v,
443 TOXAV_ERR_SEND_FRAME *error);
444/** 677/**
445 * Send an audio frame to a friend. 678 * Send an audio frame to a friend.
446 * 679 *
@@ -461,19 +694,56 @@ bool toxav_send_video_frame(ToxAV *av, uint32_t friend_number,
461 * @param sampling_rate Audio sampling rate used in this frame. Valid sampling 694 * @param sampling_rate Audio sampling rate used in this frame. Valid sampling
462 * rates are 8000, 12000, 16000, 24000, or 48000. 695 * rates are 8000, 12000, 16000, 24000, or 48000.
463 */ 696 */
464bool toxav_send_audio_frame(ToxAV *av, uint32_t friend_number, 697bool toxav_audio_send_frame(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, TOXAV_ERR_SEND_FRAME *error);
465 int16_t const *pcm, 698
466 size_t sample_count, 699/**
467 uint8_t channels, 700 * Send a video frame to a friend.
468 uint32_t sampling_rate, 701 *
469 TOXAV_ERR_SEND_FRAME *error); 702 * Y - plane should be of size: height * width
703 * U - plane should be of size: (height/2) * (width/2)
704 * V - plane should be of size: (height/2) * (width/2)
705 *
706 * @param friend_number The friend number of the friend to which to send a video
707 * frame.
708 * @param width Width of the frame in pixels.
709 * @param height Height of the frame in pixels.
710 * @param y Y (Luminance) plane data.
711 * @param u U (Chroma) plane data.
712 * @param v V (Chroma) plane data.
713 * @param a A (Alpha) plane data.
714 */
715bool toxav_video_send_frame(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, const uint8_t *a, TOXAV_ERR_SEND_FRAME *error);
716
717
470/******************************************************************************* 718/*******************************************************************************
471 * 719 *
472 * :: A/V receiving 720 * :: A/V receiving
473 * 721 *
474 ******************************************************************************/ 722 ******************************************************************************/
723
724
725
475/** 726/**
476 * The function type for the `receive_video_frame` callback. 727 * The function type for the audio_receive_frame callback.
728 *
729 * @param friend_number The friend number of the friend who sent an audio frame.
730 * @param pcm An array of audio samples (sample_count * channels elements).
731 * @param sample_count The number of audio samples per channel in the PCM array.
732 * @param channels Number of audio channels.
733 * @param sampling_rate Sampling rate used in this frame.
734 *
735 */
736typedef void toxav_audio_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, const int16_t *pcm, size_t sample_count, uint8_t channels, uint32_t sampling_rate, void *user_data);
737
738
739/**
740 * Set the callback for the `audio_receive_frame` event. Pass NULL to unset.
741 *
742 */
743void toxav_callback_audio_receive_frame(ToxAV *toxAV, toxav_audio_receive_frame_cb *callback, void *user_data);
744
745/**
746 * The function type for the video_receive_frame callback.
477 * 747 *
478 * @param friend_number The friend number of the friend who sent a video frame. 748 * @param friend_number The friend number of the friend who sent a video frame.
479 * @param width Width of the frame in pixels. 749 * @param width Width of the frame in pixels.
@@ -482,44 +752,26 @@ bool toxav_send_audio_frame(ToxAV *av, uint32_t friend_number,
482 * @param u 752 * @param u
483 * @param v Plane data. 753 * @param v Plane data.
484 * The size of plane data is derived from width and height where 754 * The size of plane data is derived from width and height where
485 * Y = width * height, U = (width/2) * (height/2) and V = (width/2) * (height/2). 755 * Y = MAX(width, abs(ystride)) * height,
756 * U = MAX(width/2, abs(ustride)) * (height/2) and
757 * V = MAX(width/2, abs(vstride)) * (height/2).
758 * A = MAX(width, abs(astride)) * height.
486 * @param ystride 759 * @param ystride
487 * @param ustride 760 * @param ustride
488 * @param vstride Strides data. 761 * @param vstride
489 */ 762 * @param astride Strides data. Strides represent padding for each plane
490typedef void toxav_receive_video_frame_cb(ToxAV *av, uint32_t friend_number, 763 * that may or may not be present. You must handle strides in
491 uint16_t width, uint16_t height, 764 * your image processing code. Strides are negative if the
492 uint8_t const *y, uint8_t const *u, uint8_t const *v, 765 * image is bottom-up hence why you MUST abs() it when
493 int32_t ystride, int32_t ustride, int32_t vstride, 766 * calculating plane buffer size.
494 void *user_data);
495/**
496 * Set the callback for the `receive_video_frame` event. Pass NULL to unset.
497 */ 767 */
498void toxav_callback_receive_video_frame(ToxAV *av, toxav_receive_video_frame_cb *function, void *user_data); 768typedef void toxav_video_receive_frame_cb(ToxAV *toxAV, uint32_t friend_number, uint16_t width, uint16_t height, const uint8_t *y, const uint8_t *u, const uint8_t *v, const uint8_t *a, int32_t ystride, int32_t ustride, int32_t vstride, int32_t astride, void *user_data);
769
770
499/** 771/**
500 * The function type for the `receive_audio_frame` callback. 772 * Set the callback for the `video_receive_frame` event. Pass NULL to unset.
501 *
502 * @param friend_number The friend number of the friend who sent an audio frame.
503 * @param pcm An array of audio samples (sample_count * channels elements).
504 * @param sample_count The number of audio samples per channel in the PCM array.
505 * @param channels Number of audio channels.
506 * @param sampling_rate Sampling rate used in this frame.
507 * 773 *
508 * @see toxav_send_audio_frame for the audio format.
509 */
510typedef void toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number,
511 int16_t const *pcm,
512 size_t sample_count,
513 uint8_t channels,
514 uint32_t sampling_rate,
515 void *user_data);
516/**
517 * Set the callback for the `receive_audio_frame` event. Pass NULL to unset.
518 */ 774 */
519void toxav_callback_receive_audio_frame(ToxAV *av, toxav_receive_audio_frame_cb *function, void *user_data); 775void toxav_callback_video_receive_frame(ToxAV *toxAV, toxav_video_receive_frame_cb *callback, void *user_data);
520 776
521#ifdef __cplusplus
522}
523#endif 777#endif
524
525#endif /* TOXAV_H */
diff --git a/toxav/video.c b/toxav/video.c
index fe57387f..690b3bd4 100644
--- a/toxav/video.c
+++ b/toxav/video.c
@@ -42,7 +42,7 @@ typedef struct { uint16_t size; uint8_t data[]; } Payload;
42bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate); 42bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate);
43 43
44 44
45VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb* cb, void* cb_data, uint32_t mvfpsz) 45VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb* cb, void* cb_data, uint32_t mvfpsz)
46{ 46{
47 VCSession *vc = calloc(sizeof(VCSession), 1); 47 VCSession *vc = calloc(sizeof(VCSession), 1);
48 48
@@ -141,8 +141,9 @@ void vc_do(VCSession* vc)
141 for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) { 141 for (; dest; dest = vpx_codec_get_frame(vc->decoder, &iter)) {
142 if (vc->vcb.first) 142 if (vc->vcb.first)
143 vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h, 143 vc->vcb.first(vc->av, vc->friend_number, dest->d_w, dest->d_h,
144 (const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1], (const uint8_t*)dest->planes[2], 144 (const uint8_t*)dest->planes[0], (const uint8_t*)dest->planes[1],
145 dest->stride[0], dest->stride[1], dest->stride[2], vc->vcb.second); 145 (const uint8_t*)dest->planes[2], (const uint8_t*)dest->planes[3],
146 dest->stride[0], dest->stride[1], dest->stride[2], dest->stride[3], vc->vcb.second);
146 147
147 vpx_img_free(dest); 148 vpx_img_free(dest);
148 } 149 }
diff --git a/toxav/video.h b/toxav/video.h
index 8da15578..96d3205d 100644
--- a/toxav/video.h
+++ b/toxav/video.h
@@ -71,7 +71,7 @@ typedef struct VCSession_s {
71 ToxAV *av; 71 ToxAV *av;
72 uint32_t friend_number; 72 uint32_t friend_number;
73 73
74 PAIR(toxav_receive_video_frame_cb *, void *) vcb; /* Video frame receive callback */ 74 PAIR(toxav_video_receive_frame_cb *, void *) vcb; /* Video frame receive callback */
75 75
76 pthread_mutex_t queue_mutex[1]; 76 pthread_mutex_t queue_mutex[1];
77} VCSession; 77} VCSession;
@@ -79,7 +79,7 @@ typedef struct VCSession_s {
79/* 79/*
80 * Create new Video Codec session. 80 * Create new Video Codec session.
81 */ 81 */
82VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb *cb, void *cb_data, uint32_t mvfpsz); 82VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_video_receive_frame_cb *cb, void *cb_data, uint32_t mvfpsz);
83/* 83/*
84 * Kill the Video Codec session. 84 * Kill the Video Codec session.
85 */ 85 */