diff options
Diffstat (limited to 'toxav/toxav.c')
-rw-r--r-- | toxav/toxav.c | 374 |
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); | |||
122 | void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate); | 122 | void ba_set(ToxAvBitrateAdapter* ba, uint32_t bit_rate); |
123 | bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba); | 123 | bool ba_shoud_send_dummy(ToxAvBitrateAdapter* ba); |
124 | 124 | ||
125 | uint32_t toxav_version_major(void) | ||
126 | { | ||
127 | return 0; | ||
128 | } | ||
129 | uint32_t toxav_version_minor(void) | ||
130 | { | ||
131 | return 0; | ||
132 | } | ||
133 | uint32_t toxav_version_patch(void) | ||
134 | { | ||
135 | return 0; | ||
136 | } | ||
137 | bool 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 | |||
125 | ToxAV* toxav_new(Tox* tox, TOXAV_ERR_NEW* error) | 146 | ToxAV* 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 | ||
207 | Tox* toxav_get_tox(ToxAV* av) | 228 | Tox* 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 | ||
575 | void toxav_callback_video_bit_rate_status(ToxAV* av, toxav_video_bit_rate_status_cb* function, void* user_data) | 589 | void 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 | ||
583 | bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error) | 597 | bool 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 | ||
634 | void toxav_callback_audio_bit_rate_status(ToxAV* av, toxav_audio_bit_rate_status_cb* function, void* user_data) | 649 | void 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 | ||
642 | bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE* error) | 657 | bool 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 | ||
694 | bool 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) | 708 | bool 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 | |||
803 | END: | ||
804 | if (error) | ||
805 | *error = rc; | ||
806 | |||
807 | return rc == TOXAV_ERR_SEND_FRAME_OK; | ||
808 | } | ||
809 | |||
810 | bool 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 | ||
859 | bool 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) | 979 | void 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 | |||
954 | END: | ||
955 | if (error) | ||
956 | *error = rc; | ||
957 | |||
958 | return rc == TOXAV_ERR_SEND_FRAME_OK; | ||
959 | } | 985 | } |
960 | 986 | ||
961 | void toxav_callback_receive_video_frame(ToxAV* av, toxav_receive_video_frame_cb* function, void* user_data) | 987 | void 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 | ||
969 | void 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 | * |