summaryrefslogtreecommitdiff
path: root/toxav/toxav.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxav/toxav.c')
-rw-r--r--toxav/toxav.c374
1 files changed, 196 insertions, 178 deletions
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 *