diff options
-rw-r--r-- | toxav/av_test.c | 137 | ||||
-rw-r--r-- | toxav/codec.c | 8 | ||||
-rw-r--r-- | toxav/toxav.c | 8 | ||||
-rw-r--r-- | toxav/toxav.h | 4 |
4 files changed, 120 insertions, 37 deletions
diff --git a/toxav/av_test.c b/toxav/av_test.c index 6ebe0421..507a708e 100644 --- a/toxav/av_test.c +++ b/toxav/av_test.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "../toxav/toxav.h" | 26 | #include "../toxav/toxav.h" |
27 | #include "../toxcore/tox.h" | 27 | #include "../toxcore/tox.h" |
28 | #include "../toxcore/util.h" | 28 | #include "../toxcore/util.h" |
29 | #include "../toxcore/network.h" /* current_time_monotonic() */ | ||
29 | 30 | ||
30 | #define LOGGING | 31 | #define LOGGING |
31 | #include "../toxcore/logger.h" | 32 | #include "../toxcore/logger.h" |
@@ -84,6 +85,9 @@ typedef struct { | |||
84 | bool incoming; | 85 | bool incoming; |
85 | uint32_t state; | 86 | uint32_t state; |
86 | uint32_t abitrate; | 87 | uint32_t abitrate; |
88 | pthread_mutex_t arb_mutex[1]; | ||
89 | RingBuffer* arb; /* Audio ring buffer */ | ||
90 | |||
87 | } CallControl; | 91 | } CallControl; |
88 | 92 | ||
89 | struct toxav_thread_data { | 93 | struct toxav_thread_data { |
@@ -95,6 +99,32 @@ struct toxav_thread_data { | |||
95 | const char* vdout = "AV Test"; /* Video output */ | 99 | const char* vdout = "AV Test"; /* Video output */ |
96 | PaStream* adout = NULL; /* Audio output */ | 100 | PaStream* adout = NULL; /* Audio output */ |
97 | 101 | ||
102 | |||
103 | typedef struct { | ||
104 | uint16_t size; | ||
105 | int16_t data[]; | ||
106 | } frame; | ||
107 | |||
108 | void* pa_write_thread (void* d) | ||
109 | { | ||
110 | /* The purpose of this thread is to make sure Pa_WriteStream will not block | ||
111 | * toxav_iterate thread | ||
112 | */ | ||
113 | CallControl* cc = d; | ||
114 | |||
115 | while (Pa_IsStreamActive(adout)) { | ||
116 | frame* f; | ||
117 | pthread_mutex_lock(cc->arb_mutex); | ||
118 | if (rb_read(cc->arb, (void**)&f)) { | ||
119 | pthread_mutex_unlock(cc->arb_mutex); | ||
120 | Pa_WriteStream(adout, f->data, f->size); | ||
121 | free(f); | ||
122 | } else | ||
123 | pthread_mutex_unlock(cc->arb_mutex); | ||
124 | } | ||
125 | } | ||
126 | |||
127 | |||
98 | /** | 128 | /** |
99 | * Callbacks | 129 | * Callbacks |
100 | */ | 130 | */ |
@@ -106,15 +136,38 @@ void t_toxav_call_cb(ToxAV *av, uint32_t friend_number, bool audio_enabled, bool | |||
106 | void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data) | 136 | void t_toxav_call_state_cb(ToxAV *av, uint32_t friend_number, uint32_t state, void *user_data) |
107 | { | 137 | { |
108 | ((CallControl*)user_data)->state = state; | 138 | ((CallControl*)user_data)->state = state; |
139 | uint32_t abitrate = ((CallControl*)user_data)->abitrate; | ||
109 | 140 | ||
110 | if (state & TOXAV_CALL_STATE_INCREASE_AUDIO_BITRATE) { | 141 | if (state & TOXAV_CALL_STATE_INCREASE_AUDIO_BITRATE) { |
111 | uint32_t bitrate = ((CallControl*)user_data)->abitrate; | ||
112 | 142 | ||
113 | if (bitrate < 64) { | 143 | // /* NOTE: I'm using values 8, 16, 24, 48, 64. You can use whatever OPUS supports. */ |
114 | printf("Changing bitrate to: %d\n", 64); | 144 | // switch (abitrate) { |
115 | toxav_set_audio_bit_rate(av, friend_number, 64, 0); | 145 | // case 8: abitrate = 16; break; |
116 | } | 146 | // case 16: abitrate = 24; break; |
117 | } else if (state & TOXAV_CALL_STATE_INCREASE_VIDEO_BITRATE) { | 147 | // case 24: abitrate = 48; break; |
148 | // case 48: abitrate = 64; break; | ||
149 | // default: return; | ||
150 | // } | ||
151 | // | ||
152 | // printf("Increasing bitrate to: %d\n", abitrate); | ||
153 | // toxav_set_audio_bit_rate(av, friend_number, abitrate, 0); | ||
154 | |||
155 | } else if (state & TOXAV_CALL_STATE_DECREASE_AUDIO_BITRATE) { | ||
156 | // /* NOTE: I'm using values 8, 16, 24, 48, 64. You can use whatever OPUS supports. */ | ||
157 | // switch (abitrate) { | ||
158 | // case 16: abitrate = 8; break; | ||
159 | // case 24: abitrate = 16; break; | ||
160 | // case 48: abitrate = 24; break; | ||
161 | // case 64: abitrate = 48; break; | ||
162 | // default: return; | ||
163 | // } | ||
164 | // | ||
165 | // printf("Decreasing bitrate to: %d\n", abitrate); | ||
166 | // toxav_set_audio_bit_rate(av, friend_number, abitrate, 0); | ||
167 | // | ||
168 | } | ||
169 | |||
170 | if (state & TOXAV_CALL_STATE_INCREASE_VIDEO_BITRATE) { | ||
118 | 171 | ||
119 | } else { | 172 | } else { |
120 | printf("Handling CALL STATE callback: %d\n", state); | 173 | printf("Handling CALL STATE callback: %d\n", state); |
@@ -158,7 +211,16 @@ void t_toxav_receive_audio_frame_cb(ToxAV *av, uint32_t friend_number, | |||
158 | uint32_t sampling_rate, | 211 | uint32_t sampling_rate, |
159 | void *user_data) | 212 | void *user_data) |
160 | { | 213 | { |
161 | Pa_WriteStream(adout, pcm, sample_count/channels); | 214 | CallControl* cc = user_data; |
215 | frame* f = malloc(sizeof(frame) + sample_count * sizeof(int16_t)); | ||
216 | memcpy(f->data, pcm, sample_count); | ||
217 | f->size = sample_count/channels; | ||
218 | |||
219 | pthread_mutex_lock(cc->arb_mutex); | ||
220 | free(rb_write(cc->arb, f)); | ||
221 | pthread_mutex_unlock(cc->arb_mutex); | ||
222 | |||
223 | // Pa_WriteStream(adout, pcm, sample_count/channels); | ||
162 | } | 224 | } |
163 | void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) | 225 | void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) |
164 | { | 226 | { |
@@ -220,6 +282,7 @@ void initialize_tox(Tox** bootstrap, ToxAV** AliceAV, CallControl* AliceCC, ToxA | |||
220 | *BobAV = toxav_new(Bob, &rc); | 282 | *BobAV = toxav_new(Bob, &rc); |
221 | assert(rc == TOXAV_ERR_NEW_OK); | 283 | assert(rc == TOXAV_ERR_NEW_OK); |
222 | 284 | ||
285 | |||
223 | /* Alice */ | 286 | /* Alice */ |
224 | toxav_callback_call(*AliceAV, t_toxav_call_cb, AliceCC); | 287 | toxav_callback_call(*AliceAV, t_toxav_call_cb, AliceCC); |
225 | toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC); | 288 | toxav_callback_call_state(*AliceAV, t_toxav_call_state_cb, AliceCC); |
@@ -255,7 +318,9 @@ void* iterate_toxav (void * data) | |||
255 | int rc = MIN(toxav_iteration_interval(data_cast->AliceAV), toxav_iteration_interval(data_cast->BobAV)); | 318 | int rc = MIN(toxav_iteration_interval(data_cast->AliceAV), toxav_iteration_interval(data_cast->BobAV)); |
256 | 319 | ||
257 | // cvWaitKey(10); | 320 | // cvWaitKey(10); |
258 | c_sleep(10); | 321 | printf("\rSleeping for: %d ", rc); |
322 | fflush(stdout); | ||
323 | c_sleep(rc); | ||
259 | } | 324 | } |
260 | 325 | ||
261 | data_cast->sig = 1; | 326 | data_cast->sig = 1; |
@@ -330,6 +395,7 @@ int print_help (const char* name) | |||
330 | 395 | ||
331 | int main (int argc, char** argv) | 396 | int main (int argc, char** argv) |
332 | { | 397 | { |
398 | freopen("/dev/zero", "w", stderr); | ||
333 | Pa_Initialize(); | 399 | Pa_Initialize(); |
334 | 400 | ||
335 | struct stat st; | 401 | struct stat st; |
@@ -669,7 +735,13 @@ int main (int argc, char** argv) | |||
669 | memset(&AliceCC, 0, sizeof(CallControl)); | 735 | memset(&AliceCC, 0, sizeof(CallControl)); |
670 | memset(&BobCC, 0, sizeof(CallControl)); | 736 | memset(&BobCC, 0, sizeof(CallControl)); |
671 | 737 | ||
672 | AliceCC.abitrate = BobCC.abitrate = 8; | 738 | pthread_mutex_init(AliceCC.arb_mutex, NULL); |
739 | pthread_mutex_init(BobCC.arb_mutex, NULL); | ||
740 | |||
741 | AliceCC.arb = rb_new(16); | ||
742 | BobCC.arb = rb_new(16); | ||
743 | |||
744 | AliceCC.abitrate = BobCC.abitrate = 16; | ||
673 | 745 | ||
674 | { /* Call */ | 746 | { /* Call */ |
675 | TOXAV_ERR_CALL rc; | 747 | TOXAV_ERR_CALL rc; |
@@ -704,21 +776,6 @@ int main (int argc, char** argv) | |||
704 | } | 776 | } |
705 | 777 | ||
706 | 778 | ||
707 | int frame_size = (af_info.samplerate * audio_frame_duration / 1000) * af_info.channels; | ||
708 | |||
709 | struct PaStreamParameters output; | ||
710 | output.device = audio_out_dev_idx; | ||
711 | output.channelCount = af_info.channels; | ||
712 | output.sampleFormat = paInt16; | ||
713 | output.suggestedLatency = audio_dev->defaultHighOutputLatency; | ||
714 | output.hostApiSpecificStreamInfo = NULL; | ||
715 | |||
716 | PaError err = Pa_OpenStream(&adout, NULL, &output, af_info.samplerate, frame_size, paNoFlag, NULL, NULL); | ||
717 | assert(err == paNoError); | ||
718 | |||
719 | err = Pa_StartStream(adout); | ||
720 | assert(err == paNoError); | ||
721 | |||
722 | int16_t PCM[5760]; | 779 | int16_t PCM[5760]; |
723 | 780 | ||
724 | time_t start_time = time(NULL); | 781 | time_t start_time = time(NULL); |
@@ -736,8 +793,25 @@ int main (int argc, char** argv) | |||
736 | pthread_create(&dect, NULL, iterate_toxav, &data); | 793 | pthread_create(&dect, NULL, iterate_toxav, &data); |
737 | pthread_detach(dect); | 794 | pthread_detach(dect); |
738 | 795 | ||
796 | |||
797 | int frame_size = (af_info.samplerate * audio_frame_duration / 1000) * af_info.channels; | ||
798 | |||
799 | struct PaStreamParameters output; | ||
800 | output.device = audio_out_dev_idx; | ||
801 | output.channelCount = af_info.channels; | ||
802 | output.sampleFormat = paInt16; | ||
803 | output.suggestedLatency = audio_dev->defaultHighOutputLatency; | ||
804 | output.hostApiSpecificStreamInfo = NULL; | ||
805 | |||
806 | PaError err = Pa_OpenStream(&adout, NULL, &output, af_info.samplerate, frame_size, paNoFlag, NULL, NULL); | ||
807 | assert(err == paNoError); | ||
808 | |||
809 | err = Pa_StartStream(adout); | ||
810 | assert(err == paNoError); | ||
811 | |||
739 | printf("Sample rate %d\n", af_info.samplerate); | 812 | printf("Sample rate %d\n", af_info.samplerate); |
740 | while ( start_time + expected_time > time(NULL) ) { | 813 | while ( start_time + expected_time > time(NULL) ) { |
814 | uint64_t enc_start_time = current_time_monotonic(); | ||
741 | int64_t count = sf_read_short(af_handle, PCM, frame_size); | 815 | int64_t count = sf_read_short(af_handle, PCM, frame_size); |
742 | if (count > 0) { | 816 | if (count > 0) { |
743 | TOXAV_ERR_SEND_FRAME rc; | 817 | TOXAV_ERR_SEND_FRAME rc; |
@@ -746,9 +820,10 @@ int main (int argc, char** argv) | |||
746 | } | 820 | } |
747 | } | 821 | } |
748 | iterate_tox(bootstrap, AliceAV, BobAV); | 822 | iterate_tox(bootstrap, AliceAV, BobAV); |
749 | c_sleep(53); | 823 | c_sleep(abs(audio_frame_duration - (current_time_monotonic() - enc_start_time) - 1)); |
750 | } | 824 | } |
751 | 825 | ||
826 | Pa_StopStream(adout); | ||
752 | 827 | ||
753 | printf("Played file in: %lu\n", time(NULL) - start_time); | 828 | printf("Played file in: %lu\n", time(NULL) - start_time); |
754 | 829 | ||
@@ -772,7 +847,15 @@ int main (int argc, char** argv) | |||
772 | while(data.sig != 1) | 847 | while(data.sig != 1) |
773 | pthread_yield(); | 848 | pthread_yield(); |
774 | 849 | ||
775 | Pa_StopStream(adout); | 850 | pthread_mutex_destroy(AliceCC.arb_mutex); |
851 | pthread_mutex_destroy(BobCC.arb_mutex); | ||
852 | |||
853 | void* f = NULL; | ||
854 | while(rb_read(AliceCC.arb, &f)) | ||
855 | free(f); | ||
856 | |||
857 | while(rb_read(BobCC.arb, &f)) | ||
858 | free(f); | ||
776 | 859 | ||
777 | printf("Success!"); | 860 | printf("Success!"); |
778 | } | 861 | } |
diff --git a/toxav/codec.c b/toxav/codec.c index 1e8754e9..95b4d406 100644 --- a/toxav/codec.c +++ b/toxav/codec.c | |||
@@ -293,7 +293,7 @@ void cs_do(CSession *cs) | |||
293 | /* The maximum for 120 ms 48 KHz audio */ | 293 | /* The maximum for 120 ms 48 KHz audio */ |
294 | int16_t tmp[5760]; | 294 | int16_t tmp[5760]; |
295 | 295 | ||
296 | if ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) { | 296 | while ((msg = jbuf_read(cs->j_buf, &success)) || success == 2) { |
297 | LOGGED_UNLOCK(cs->queue_mutex); | 297 | LOGGED_UNLOCK(cs->queue_mutex); |
298 | 298 | ||
299 | if (success == 2) { | 299 | if (success == 2) { |
@@ -327,7 +327,8 @@ void cs_do(CSession *cs) | |||
327 | if (!reconfigure_audio_decoder(cs, cs->last_packet_sampling_rate, cs->last_packet_channel_count)) { | 327 | if (!reconfigure_audio_decoder(cs, cs->last_packet_sampling_rate, cs->last_packet_channel_count)) { |
328 | LOGGER_WARNING("Failed to reconfigure decoder!"); | 328 | LOGGER_WARNING("Failed to reconfigure decoder!"); |
329 | rtp_free_msg(NULL, msg); | 329 | rtp_free_msg(NULL, msg); |
330 | goto DONE; | 330 | continue; |
331 | // goto DONE; | ||
331 | } | 332 | } |
332 | 333 | ||
333 | rc = opus_decode(cs->audio_decoder, msg->data + 4, msg->length - 4, tmp, 5760, 0); | 334 | rc = opus_decode(cs->audio_decoder, msg->data + 4, msg->length - 4, tmp, 5760, 0); |
@@ -337,7 +338,6 @@ void cs_do(CSession *cs) | |||
337 | if (rc < 0) { | 338 | if (rc < 0) { |
338 | LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); | 339 | LOGGER_WARNING("Decoding error: %s", opus_strerror(rc)); |
339 | } else if (cs->acb.first) { | 340 | } else if (cs->acb.first) { |
340 | cs->last_packet_channel_count = 2; | ||
341 | cs->last_packet_frame_duration = (rc * 1000) / cs->last_packet_sampling_rate * cs->last_packet_channel_count; | 341 | cs->last_packet_frame_duration = (rc * 1000) / cs->last_packet_sampling_rate * cs->last_packet_channel_count; |
342 | 342 | ||
343 | cs->acb.first(cs->av, cs->friend_id, tmp, rc * cs->last_packet_channel_count, | 343 | cs->acb.first(cs->av, cs->friend_id, tmp, rc * cs->last_packet_channel_count, |
@@ -347,7 +347,7 @@ void cs_do(CSession *cs) | |||
347 | 347 | ||
348 | LOGGED_LOCK(cs->queue_mutex); | 348 | LOGGED_LOCK(cs->queue_mutex); |
349 | } | 349 | } |
350 | DONE:; | 350 | // DONE:; |
351 | } | 351 | } |
352 | 352 | ||
353 | /********************* VIDEO *********************/ | 353 | /********************* VIDEO *********************/ |
diff --git a/toxav/toxav.c b/toxav/toxav.c index 0e94e5dd..dbc06587 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c | |||
@@ -249,8 +249,8 @@ void toxav_iterate(ToxAV* av) | |||
249 | } | 249 | } |
250 | LOGGED_UNLOCK(av->mutex); | 250 | LOGGED_UNLOCK(av->mutex); |
251 | 251 | ||
252 | // av->interval = rc < av->dmssa ? 0 : (rc - av->dmssa); | 252 | av->interval = rc < av->dmssa ? 0 : (rc - av->dmssa); |
253 | av->interval = rc < 5 ? 1: rc - 5; | 253 | // av->interval = rc < 5 ? 1: rc - 5; |
254 | av->dmsst += current_time_monotonic() - start; | 254 | av->dmsst += current_time_monotonic() - start; |
255 | 255 | ||
256 | if (++av->dmssc == 3) { | 256 | if (++av->dmssc == 3) { |
@@ -993,7 +993,7 @@ void qc_do(ToxAVCall* call) | |||
993 | LOGGER_DEBUG("Suggesting lower bitrate for audio..."); | 993 | LOGGER_DEBUG("Suggesting lower bitrate for audio..."); |
994 | call->time_audio_good = 0; | 994 | call->time_audio_good = 0; |
995 | call->last_bad_audio_bit_rate = call->audio_bit_rate; | 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); | 996 | invoke_call_state(call->av, call->friend_id, TOXAV_CALL_STATE_DECREASE_AUDIO_BITRATE); |
997 | break; | 997 | break; |
998 | case rtp_StateGood: | 998 | case rtp_StateGood: |
999 | if (call->time_audio_good == 0) | 999 | if (call->time_audio_good == 0) |
@@ -1017,7 +1017,7 @@ void qc_do(ToxAVCall* call) | |||
1017 | LOGGER_DEBUG("Suggesting lower bitrate for video..."); | 1017 | LOGGER_DEBUG("Suggesting lower bitrate for video..."); |
1018 | call->time_video_good = 0; | 1018 | call->time_video_good = 0; |
1019 | call->last_bad_video_bit_rate = call->video_bit_rate; | 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); | 1020 | invoke_call_state(call->av, call->friend_id, TOXAV_CALL_STATE_DECREASE_VIDEO_BITRATE); |
1021 | break; | 1021 | break; |
1022 | case rtp_StateGood: | 1022 | case rtp_StateGood: |
1023 | if (call->time_video_good == 0) | 1023 | if (call->time_video_good == 0) |
diff --git a/toxav/toxav.h b/toxav/toxav.h index 098075b3..73e5a86c 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h | |||
@@ -215,11 +215,11 @@ typedef enum TOXAV_CALL_STATE { | |||
215 | /** | 215 | /** |
216 | * AV core suggests you to lower bitrate for audio. | 216 | * AV core suggests you to lower bitrate for audio. |
217 | */ | 217 | */ |
218 | TOXAV_CALL_STATE_LOWER_AUDIO_BITRATE = 32, | 218 | TOXAV_CALL_STATE_DECREASE_AUDIO_BITRATE = 32, |
219 | /** | 219 | /** |
220 | * AV core suggests you to lower bitrate for video. | 220 | * AV core suggests you to lower bitrate for video. |
221 | */ | 221 | */ |
222 | TOXAV_CALL_STATE_LOWER_VIDEO_BITRATE = 64, | 222 | TOXAV_CALL_STATE_DECREASE_VIDEO_BITRATE = 64, |
223 | /** | 223 | /** |
224 | * AV core suggests you to increase bitrate for audio. | 224 | * AV core suggests you to increase bitrate for audio. |
225 | */ | 225 | */ |