diff options
author | mannol <eniz_vukovic@hotmail.com> | 2015-05-22 23:22:31 +0200 |
---|---|---|
committer | mannol <eniz_vukovic@hotmail.com> | 2015-05-22 23:22:31 +0200 |
commit | 3100042a2b78f4f80d23f67e6113797cd8fb5df0 (patch) | |
tree | c226f4b25002784d93f9bb6415be4b55b76cddd1 /toxav | |
parent | 62c40af1a0c557ba8c77583c972ae3af9af15cf1 (diff) | |
parent | 2ba076ac5cc6efb5eb41fb4aa6a77a151885f26c (diff) |
Updated with master
Diffstat (limited to 'toxav')
-rw-r--r-- | toxav/audio.c | 2 | ||||
-rw-r--r-- | toxav/audio.h | 4 | ||||
-rw-r--r-- | toxav/msi.c | 2 | ||||
-rw-r--r-- | toxav/msi.h | 8 | ||||
-rw-r--r-- | toxav/toxav.c | 374 | ||||
-rw-r--r-- | toxav/toxav.h | 820 | ||||
-rw-r--r-- | toxav/video.c | 7 | ||||
-rw-r--r-- | toxav/video.h | 4 |
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 | ||
41 | ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data) | 41 | ACSession* 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 | */ |
70 | ACSession* ac_new(ToxAV* av, uint32_t friend_number, toxav_receive_audio_frame_cb *cb, void *cb_data); | 70 | ACSession* 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 | */ |
52 | typedef enum { | 52 | typedef 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); | |||
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 | * |
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 |
30 | extern "C" { | 30 | extern "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 | */ |
40 | typedef struct ToxAV ToxAV; | ||
41 | #ifndef TOX_DEFINED | 65 | #ifndef TOX_DEFINED |
42 | #define TOX_DEFINED | 66 | #define TOX_DEFINED |
67 | typedef 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 | */ |
47 | typedef 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 | ||
83 | typedef 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 | */ | ||
143 | uint32_t toxav_version_major(void); | ||
144 | |||
145 | /** | ||
146 | * Return the minor version number of the library. | ||
147 | */ | ||
148 | uint32_t toxav_version_minor(void); | ||
149 | |||
150 | /** | ||
151 | * Return the patch number of the library. | ||
152 | */ | ||
153 | uint32_t toxav_version_patch(void); | ||
154 | |||
155 | /** | ||
156 | * Return whether the compiled library version is compatible with the passed | ||
157 | * version numbers. | ||
158 | */ | ||
159 | bool 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 | |||
54 | typedef enum TOXAV_ERR_NEW { | 170 | typedef 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 | */ |
70 | ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error); | 199 | ToxAV *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 | */ |
78 | void toxav_kill(ToxAV *av); | 208 | void 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 | */ |
82 | Tox *toxav_get_tox(ToxAV *av); | 213 | Tox *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 | */ |
92 | uint32_t toxav_iteration_interval(ToxAV const *av); | 228 | uint32_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 | */ |
98 | void toxav_iterate(ToxAV *av); | 235 | void toxav_iterate(ToxAV *toxAV); |
236 | |||
237 | |||
99 | /******************************************************************************* | 238 | /******************************************************************************* |
100 | * | 239 | * |
101 | * :: Call setup | 240 | * :: Call setup |
102 | * | 241 | * |
103 | ******************************************************************************/ | 242 | ******************************************************************************/ |
243 | |||
244 | |||
245 | |||
104 | typedef enum TOXAV_ERR_CALL { | 246 | typedef 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 | */ |
142 | bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_CALL *error); | 296 | bool 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 | */ |
146 | typedef void toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool video_enabled, void *user_data); | 305 | typedef 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 | */ |
152 | void toxav_callback_call(ToxAV *av, toxav_call_cb *function, void *user_data); | 312 | void toxav_callback_call(ToxAV *toxAV, toxav_call_cb *callback, void *user_data); |
313 | |||
153 | typedef enum TOXAV_ERR_ANSWER { | 314 | typedef 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 | */ |
187 | bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, TOXAV_ERR_ANSWER *error); | 359 | bool 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 | |||
193 | enum TOXAV_CALL_STATE { | 370 | enum 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 | */ |
228 | typedef void toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data); | 417 | typedef 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 | */ |
234 | void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *function, void *user_data); | 424 | void 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 | |||
240 | typedef enum TOXAV_CALL_CONTROL { | 435 | typedef 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 | |||
272 | typedef enum TOXAV_ERR_CALL_CONTROL { | 481 | typedef 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 | */ |
303 | bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error); | 517 | bool 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 | ******************************************************************************/ |
309 | typedef 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. | 528 | typedef 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 | */ |
337 | typedef void toxav_audio_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); | 566 | typedef 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 | */ |
341 | void toxav_callback_audio_bit_rate_status(ToxAV *av, toxav_audio_bit_rate_status_cb *function, void *user_data); | 573 | void 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 | */ |
357 | bool toxav_set_audio_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); | 590 | bool 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 | */ |
371 | typedef void toxav_video_bit_rate_status_cb(ToxAV *av, uint32_t friend_number, bool stable, uint32_t bit_rate, void *user_data); | 605 | typedef 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 | */ |
375 | void toxav_callback_video_bit_rate_status(ToxAV *av, toxav_video_bit_rate_status_cb *function, void *user_data); | 612 | void 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 | */ |
391 | bool toxav_set_video_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, bool force, TOXAV_ERR_BIT_RATE *error); | 629 | bool 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 | |
400 | typedef enum TOXAV_ERR_SEND_FRAME { | 640 | typedef 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 | */ | ||
440 | bool 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 | */ |
464 | bool toxav_send_audio_frame(ToxAV *av, uint32_t friend_number, | 697 | bool 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 | */ | ||
715 | bool 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 | */ | ||
736 | typedef 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 | */ | ||
743 | void 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 |
490 | typedef 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 | */ |
498 | void toxav_callback_receive_video_frame(ToxAV *av, toxav_receive_video_frame_cb *function, void *user_data); | 768 | typedef 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 | */ | ||
510 | typedef 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 | */ |
519 | void toxav_callback_receive_audio_frame(ToxAV *av, toxav_receive_audio_frame_cb *function, void *user_data); | 775 | void 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; | |||
42 | bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate); | 42 | bool create_video_encoder (vpx_codec_ctx_t* dest, int32_t bit_rate); |
43 | 43 | ||
44 | 44 | ||
45 | VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb* cb, void* cb_data, uint32_t mvfpsz) | 45 | VCSession* 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 | */ |
82 | VCSession* vc_new(ToxAV* av, uint32_t friend_number, toxav_receive_video_frame_cb *cb, void *cb_data, uint32_t mvfpsz); | 82 | VCSession* 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 | */ |