diff options
author | mannol <eniz_vukovic@hotmail.com> | 2015-04-16 02:00:34 +0200 |
---|---|---|
committer | mannol <eniz_vukovic@hotmail.com> | 2015-04-16 02:00:34 +0200 |
commit | da6c17222f54c933c826e9c557e66629ee57790f (patch) | |
tree | 2cf5e0ff002bef5d69f0048475ea7becc11bd389 /toxav/toxav.c | |
parent | 2465f486acd90ed8395c8a83a13af09ecd024c98 (diff) |
The pretty basic adaptive bitrate is *working*
Diffstat (limited to 'toxav/toxav.c')
-rw-r--r-- | toxav/toxav.c | 165 |
1 files changed, 117 insertions, 48 deletions
diff --git a/toxav/toxav.c b/toxav/toxav.c index 721b9d91..0e94e5dd 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -60,6 +60,12 @@ typedef struct ToxAVCall_s { | |||
60 | uint8_t last_self_capabilities; | 60 | uint8_t last_self_capabilities; |
61 | uint8_t last_peer_capabilities; | 61 | uint8_t last_peer_capabilities; |
62 | 62 | ||
63 | /** Quality control */ | ||
64 | uint64_t time_audio_good; | ||
65 | uint32_t last_bad_audio_bit_rate; | ||
66 | uint64_t time_video_good; | ||
67 | uint32_t last_bad_video_bit_rate; | ||
68 | |||
63 | struct ToxAVCall_s *prev; | 69 | struct ToxAVCall_s *prev; |
64 | struct ToxAVCall_s *next; | 70 | struct ToxAVCall_s *next; |
65 | } ToxAVCall; | 71 | } ToxAVCall; |
@@ -96,11 +102,13 @@ int callback_end(void* toxav_inst, MSICall* call); | |||
96 | int callback_error(void* toxav_inst, MSICall* call); | 102 | int callback_error(void* toxav_inst, MSICall* call); |
97 | int callback_capabilites(void* toxav_inst, MSICall* call); | 103 | int callback_capabilites(void* toxav_inst, MSICall* call); |
98 | 104 | ||
105 | bool audio_bitrate_invalid(uint32_t bitrate); | ||
106 | bool video_bitrate_invalid(uint32_t bitrate); | ||
107 | void invoke_call_state(ToxAV* av, uint32_t friend_number, uint32_t state); | ||
99 | ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error); | 108 | ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error); |
100 | ToxAVCall* call_get(ToxAV* av, uint32_t friend_number); | 109 | ToxAVCall* call_get(ToxAV* av, uint32_t friend_number); |
110 | void qc_do(ToxAVCall* call); | ||
101 | void call_remove(ToxAVCall* call); | 111 | void call_remove(ToxAVCall* call); |
102 | bool audio_bitrate_invalid(uint32_t bitrate); | ||
103 | bool video_bitrate_invalid(uint32_t bitrate); | ||
104 | bool call_prepare_transmission(ToxAVCall* call); | 112 | bool call_prepare_transmission(ToxAVCall* call); |
105 | void call_kill_transmission(ToxAVCall* call); | 113 | void call_kill_transmission(ToxAVCall* call); |
106 | 114 | ||
@@ -220,8 +228,9 @@ void toxav_iterate(ToxAV* av) | |||
220 | LOGGED_UNLOCK(av->mutex); | 228 | LOGGED_UNLOCK(av->mutex); |
221 | 229 | ||
222 | cs_do(i->cs); | 230 | cs_do(i->cs); |
223 | rtp_do(i->rtps[0]); | 231 | rtp_do(i->rtps[audio_index]); |
224 | rtp_do(i->rtps[1]); | 232 | rtp_do(i->rtps[video_index]); |
233 | qc_do(i); | ||
225 | 234 | ||
226 | if (i->last_self_capabilities & msi_CapRAudio) /* Receiving audio */ | 235 | if (i->last_self_capabilities & msi_CapRAudio) /* Receiving audio */ |
227 | rc = MIN(i->cs->last_packet_frame_duration, rc); | 236 | rc = MIN(i->cs->last_packet_frame_duration, rc); |
@@ -516,8 +525,10 @@ bool toxav_set_audio_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t audio_ | |||
516 | goto END; | 525 | goto END; |
517 | } | 526 | } |
518 | 527 | ||
519 | /* NOTE: no need to lock*/ | 528 | /* Decoding mutex is locked because of quality control */ |
529 | LOGGED_LOCK(call->mutex_decoding); | ||
520 | call->audio_bit_rate = audio_bit_rate; | 530 | call->audio_bit_rate = audio_bit_rate; |
531 | LOGGED_UNLOCK(call->mutex_decoding); | ||
521 | LOGGED_UNLOCK(av->mutex); | 532 | LOGGED_UNLOCK(av->mutex); |
522 | 533 | ||
523 | END: | 534 | END: |
@@ -550,8 +561,10 @@ bool toxav_set_video_bit_rate(ToxAV* av, uint32_t friend_number, uint32_t video_ | |||
550 | goto END; | 561 | goto END; |
551 | } | 562 | } |
552 | 563 | ||
553 | /* NOTE: no need to lock*/ | 564 | /* Decoding mutex is locked because of quality control */ |
565 | LOGGED_LOCK(call->mutex_decoding); | ||
554 | call->video_bit_rate = video_bit_rate; | 566 | call->video_bit_rate = video_bit_rate; |
567 | LOGGED_UNLOCK(call->mutex_decoding); | ||
555 | LOGGED_UNLOCK(av->mutex); | 568 | LOGGED_UNLOCK(av->mutex); |
556 | 569 | ||
557 | END: | 570 | END: |
@@ -813,8 +826,7 @@ int callback_start(void* toxav_inst, MSICall* call) | |||
813 | return -1; | 826 | return -1; |
814 | } | 827 | } |
815 | 828 | ||
816 | if (toxav->scb.first) | 829 | invoke_call_state(toxav, call->friend_id, call->peer_capabilities); |
817 | toxav->scb.first(toxav, call->friend_id, call->peer_capabilities, toxav->scb.second); | ||
818 | 830 | ||
819 | LOGGED_UNLOCK(toxav->mutex); | 831 | LOGGED_UNLOCK(toxav->mutex); |
820 | return 0; | 832 | return 0; |
@@ -825,8 +837,7 @@ int callback_end(void* toxav_inst, MSICall* call) | |||
825 | ToxAV* toxav = toxav_inst; | 837 | ToxAV* toxav = toxav_inst; |
826 | LOGGED_LOCK(toxav->mutex); | 838 | LOGGED_LOCK(toxav->mutex); |
827 | 839 | ||
828 | if (toxav->scb.first) | 840 | invoke_call_state(toxav, call->friend_id, TOXAV_CALL_STATE_END); |
829 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_END, toxav->scb.second); | ||
830 | 841 | ||
831 | call_kill_transmission(call->av_call); | 842 | call_kill_transmission(call->av_call); |
832 | call_remove(call->av_call); | 843 | call_remove(call->av_call); |
@@ -840,8 +851,7 @@ int callback_error(void* toxav_inst, MSICall* call) | |||
840 | ToxAV* toxav = toxav_inst; | 851 | ToxAV* toxav = toxav_inst; |
841 | LOGGED_LOCK(toxav->mutex); | 852 | LOGGED_LOCK(toxav->mutex); |
842 | 853 | ||
843 | if (toxav->scb.first) | 854 | invoke_call_state(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR); |
844 | toxav->scb.first(toxav, call->friend_id, TOXAV_CALL_STATE_ERROR, toxav->scb.second); | ||
845 | 855 | ||
846 | call_kill_transmission(call->av_call); | 856 | call_kill_transmission(call->av_call); |
847 | call_remove(call->av_call); | 857 | call_remove(call->av_call); |
@@ -857,8 +867,7 @@ int callback_capabilites(void* toxav_inst, MSICall* call) | |||
857 | 867 | ||
858 | /* TODO modify cs? */ | 868 | /* TODO modify cs? */ |
859 | 869 | ||
860 | if (toxav->scb.first) | 870 | invoke_call_state(toxav, call->friend_id, call->peer_capabilities); |
861 | toxav->scb.first(toxav, call->friend_id, call->peer_capabilities, toxav->scb.second); | ||
862 | 871 | ||
863 | LOGGED_UNLOCK(toxav->mutex); | 872 | LOGGED_UNLOCK(toxav->mutex); |
864 | return 0; | 873 | return 0; |
@@ -878,6 +887,12 @@ bool video_bitrate_invalid(uint32_t bitrate) | |||
878 | return false; | 887 | return false; |
879 | } | 888 | } |
880 | 889 | ||
890 | void invoke_call_state(ToxAV* av, uint32_t friend_number, uint32_t state) | ||
891 | { | ||
892 | if (av->scb.first) | ||
893 | av->scb.first(av, friend_number, state, av->scb.second); | ||
894 | } | ||
895 | |||
881 | ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error) | 896 | ToxAVCall* call_new(ToxAV* av, uint32_t friend_number, TOXAV_ERR_CALL* error) |
882 | { | 897 | { |
883 | /* Assumes mutex locked */ | 898 | /* Assumes mutex locked */ |
@@ -968,6 +983,94 @@ ToxAVCall* call_get(ToxAV* av, uint32_t friend_number) | |||
968 | return av->calls[friend_number]; | 983 | return av->calls[friend_number]; |
969 | } | 984 | } |
970 | 985 | ||
986 | void qc_do(ToxAVCall* call) | ||
987 | { | ||
988 | /* Please NOTE: The quality control is rather basic, | ||
989 | * advanced algorithms will be applied in the future | ||
990 | */ | ||
991 | switch(call->rtps[audio_index]->tstate) { | ||
992 | case rtp_StateBad: | ||
993 | LOGGER_DEBUG("Suggesting lower bitrate for audio..."); | ||
994 | call->time_audio_good = 0; | ||
995 | call->last_bad_audio_bit_rate = call->audio_bit_rate; | ||
996 | invoke_call_state(call->av, call->friend_id, TOXAV_CALL_STATE_LOWER_AUDIO_BITRATE); | ||
997 | break; | ||
998 | case rtp_StateGood: | ||
999 | if (call->time_audio_good == 0) | ||
1000 | call->time_audio_good = current_time_monotonic(); | ||
1001 | else if (current_time_monotonic() - call->time_audio_good >= 30000 && | ||
1002 | 64 > call->audio_bit_rate) | ||
1003 | if (call->last_bad_audio_bit_rate > call->audio_bit_rate) { | ||
1004 | if (current_time_monotonic() - call->time_audio_good >= 45000) | ||
1005 | invoke_call_state(call->av, call->friend_id, TOXAV_CALL_STATE_INCREASE_AUDIO_BITRATE); | ||
1006 | call->last_bad_audio_bit_rate = 0; | ||
1007 | } else | ||
1008 | invoke_call_state(call->av, call->friend_id, TOXAV_CALL_STATE_INCREASE_AUDIO_BITRATE); | ||
1009 | break; | ||
1010 | case rtp_StateNormal: | ||
1011 | call->time_audio_good = 0; | ||
1012 | break; | ||
1013 | } | ||
1014 | |||
1015 | switch(call->rtps[video_index]->tstate) { | ||
1016 | case rtp_StateBad: | ||
1017 | LOGGER_DEBUG("Suggesting lower bitrate for video..."); | ||
1018 | call->time_video_good = 0; | ||
1019 | call->last_bad_video_bit_rate = call->video_bit_rate; | ||
1020 | invoke_call_state(call->av, call->friend_id, TOXAV_CALL_STATE_LOWER_VIDEO_BITRATE); | ||
1021 | break; | ||
1022 | case rtp_StateGood: | ||
1023 | if (call->time_video_good == 0) | ||
1024 | call->time_video_good = current_time_monotonic(); | ||
1025 | else if (current_time_monotonic() - call->time_video_good >= 30000) | ||
1026 | if (call->last_bad_video_bit_rate > call->video_bit_rate) { | ||
1027 | if (current_time_monotonic() - call->time_video_good >= 45000) | ||
1028 | invoke_call_state(call->av, call->friend_id, TOXAV_CALL_STATE_INCREASE_VIDEO_BITRATE); | ||
1029 | call->last_bad_video_bit_rate = 0; | ||
1030 | } else | ||
1031 | invoke_call_state(call->av, call->friend_id, TOXAV_CALL_STATE_INCREASE_VIDEO_BITRATE); | ||
1032 | break; | ||
1033 | case rtp_StateNormal: | ||
1034 | call->time_video_good = 0; | ||
1035 | break; | ||
1036 | } | ||
1037 | |||
1038 | } | ||
1039 | |||
1040 | void call_remove(ToxAVCall* call) | ||
1041 | { | ||
1042 | if (call == NULL) | ||
1043 | return; | ||
1044 | |||
1045 | uint32_t friend_id = call->friend_id; | ||
1046 | ToxAV* av = call->av; | ||
1047 | |||
1048 | ToxAVCall* prev = call->prev; | ||
1049 | ToxAVCall* next = call->next; | ||
1050 | |||
1051 | free(call); | ||
1052 | |||
1053 | if (prev) | ||
1054 | prev->next = next; | ||
1055 | else if (next) | ||
1056 | av->calls_head = next->friend_id; | ||
1057 | else goto CLEAR; | ||
1058 | |||
1059 | if (next) | ||
1060 | next->prev = prev; | ||
1061 | else if (prev) | ||
1062 | av->calls_tail = prev->friend_id; | ||
1063 | else goto CLEAR; | ||
1064 | |||
1065 | av->calls[friend_id] = NULL; | ||
1066 | return; | ||
1067 | |||
1068 | CLEAR: | ||
1069 | av->calls_head = av->calls_tail = 0; | ||
1070 | free(av->calls); | ||
1071 | av->calls = NULL; | ||
1072 | } | ||
1073 | |||
971 | bool call_prepare_transmission(ToxAVCall* call) | 1074 | bool call_prepare_transmission(ToxAVCall* call) |
972 | { | 1075 | { |
973 | /* Assumes mutex locked */ | 1076 | /* Assumes mutex locked */ |
@@ -1089,37 +1192,3 @@ void call_kill_transmission(ToxAVCall* call) | |||
1089 | pthread_mutex_destroy(call->mutex_video_sending); | 1192 | pthread_mutex_destroy(call->mutex_video_sending); |
1090 | pthread_mutex_destroy(call->mutex_decoding); | 1193 | pthread_mutex_destroy(call->mutex_decoding); |
1091 | } | 1194 | } |
1092 | |||
1093 | void call_remove(ToxAVCall* call) | ||
1094 | { | ||
1095 | if (call == NULL) | ||
1096 | return; | ||
1097 | |||
1098 | uint32_t friend_id = call->friend_id; | ||
1099 | ToxAV* av = call->av; | ||
1100 | |||
1101 | ToxAVCall* prev = call->prev; | ||
1102 | ToxAVCall* next = call->next; | ||
1103 | |||
1104 | free(call); | ||
1105 | |||
1106 | if (prev) | ||
1107 | prev->next = next; | ||
1108 | else if (next) | ||
1109 | av->calls_head = next->friend_id; | ||
1110 | else goto CLEAR; | ||
1111 | |||
1112 | if (next) | ||
1113 | next->prev = prev; | ||
1114 | else if (prev) | ||
1115 | av->calls_tail = prev->friend_id; | ||
1116 | else goto CLEAR; | ||
1117 | |||
1118 | av->calls[friend_id] = NULL; | ||
1119 | return; | ||
1120 | |||
1121 | CLEAR: | ||
1122 | av->calls_head = av->calls_tail = 0; | ||
1123 | free(av->calls); | ||
1124 | av->calls = NULL; | ||
1125 | } | ||