From 475f01bc1aaffc2a6b0a04909dc1b81d38573d04 Mon Sep 17 00:00:00 2001 From: iphydf Date: Sun, 12 Aug 2018 22:01:42 +0000 Subject: [PATCH] Fix style in toxav.c. * Use Camel_Snake_Case for type names. * Use at least 4 characters for constant names. I.e. `END` is a type name, but `RETURN` is a constant name. This is because `DHT` is a type name (yay consistency). * Using `min_*` functions instead of MIN, we can avoid a cast. * Use `for`-loops for for-each-frame semantics instead of `while`. * Don't use assignments as expressions. * `++i` instead of `i++`. * Function pointers are dereferenced automatically, so no need to manually do so. * Avoid void pointers that lie about not being spaghetti code. Toxcore and toxav are both spaghetti and shouldn't pretend anything else. * Don't use empty statements (e.g. no `;;` anywhere in the code). --- toxav/toxav.api.h | 23 +++- toxav/toxav.c | 295 ++++++++++++++++++++++++---------------------- toxav/toxav.h | 22 +++- 3 files changed, 191 insertions(+), 149 deletions(-) diff --git a/toxav/toxav.api.h b/toxav/toxav.api.h index 9e6cea6884..29a61f1626 100644 --- a/toxav/toxav.api.h +++ b/toxav/toxav.api.h @@ -605,6 +605,10 @@ namespace video { %{ /** * NOTE Compatibility with old toxav group calls. TODO(iphydf): remove + * + * TODO(iphydf): Use proper new API guidelines for these. E.g. don't use inline + * function types, don't have per-callback userdata, especially don't have one + * userdata per group. */ /* Create a new toxav group. * @@ -616,8 +620,9 @@ namespace video { * * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)). */ -int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, uint32_t, uint32_t, const int16_t *, unsigned int, uint8_t, - uint32_t, void *), void *userdata); +int toxav_add_av_groupchat(Tox *tox, + void (*audio_callback)(void *, uint32_t, uint32_t, const int16_t *, unsigned int, uint8_t, uint32_t, void *), + void *userdata); /* Join a AV group (you need to have been invited first.) * @@ -630,7 +635,8 @@ int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, uint32_t, ui * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)). */ int toxav_join_av_groupchat(Tox *tox, uint32_t friendnumber, const uint8_t *data, uint16_t length, - void (*audio_callback)(void *, uint32_t, uint32_t, const int16_t *, unsigned int, uint8_t, uint32_t, void *), void *userdata); + void (*audio_callback)(void *, uint32_t, uint32_t, const int16_t *, unsigned int, uint8_t, uint32_t, void *), + void *userdata); /* Send audio to the group chat. * @@ -651,5 +657,16 @@ int toxav_group_send_audio(Tox *tox, uint32_t groupnumber, const int16_t *pcm, u #ifdef __cplusplus } #endif + +typedef void toxav_group_audio_cb(Tox *tox, uint32_t groupnumber, uint32_t peernumber, const int16_t *pcm, uint32_t samples, uint8_t channels, uint32_t sample_rate, void *user_data); + +typedef TOXAV_ERR_CALL Toxav_Err_Call; +typedef TOXAV_ERR_NEW Toxav_Err_New; +typedef TOXAV_ERR_ANSWER Toxav_Err_Answer; +typedef TOXAV_ERR_CALL_CONTROL Toxav_Err_Call_Control; +typedef TOXAV_ERR_BIT_RATE_SET Toxav_Err_Bit_Rate_Set; +typedef TOXAV_ERR_SEND_FRAME Toxav_Err_Send_Frame; +typedef TOXAV_CALL_CONTROL Toxav_Call_Control; + #endif /* TOXAV_H */ %} diff --git a/toxav/toxav.c b/toxav/toxav.c index 6f47a0bca8..84e67858ae 100644 --- a/toxav/toxav.c +++ b/toxav/toxav.c @@ -128,20 +128,20 @@ int callback_capabilites(void *toxav_inst, MSICall *call); bool audio_bit_rate_invalid(uint32_t bit_rate); bool video_bit_rate_invalid(uint32_t bit_rate); bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t state); -ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, TOXAV_ERR_CALL *error); +ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, Toxav_Err_Call *error); ToxAVCall *call_get(ToxAV *av, uint32_t friend_number); ToxAVCall *call_remove(ToxAVCall *call); bool call_prepare_transmission(ToxAVCall *call); void call_kill_transmission(ToxAVCall *call); -ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error) +ToxAV *toxav_new(Tox *tox, Toxav_Err_New *error) { - TOXAV_ERR_NEW rc = TOXAV_ERR_NEW_OK; + Toxav_Err_New rc = TOXAV_ERR_NEW_OK; ToxAV *av = nullptr; if (tox == nullptr) { rc = TOXAV_ERR_NEW_NULL; - goto END; + goto RETURN; } // TODO(iphydf): Don't rely on toxcore internals. @@ -150,7 +150,7 @@ ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error) if (m->msi_packet) { rc = TOXAV_ERR_NEW_MULTIPLE; - goto END; + goto RETURN; } av = (ToxAV *)calloc(sizeof(ToxAV), 1); @@ -158,13 +158,13 @@ ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error) if (av == nullptr) { LOGGER_WARNING(m->log, "Allocation failed!"); rc = TOXAV_ERR_NEW_MALLOC; - goto END; + goto RETURN; } if (create_recursive_mutex(av->mutex) != 0) { LOGGER_WARNING(m->log, "Mutex creation failed!"); rc = TOXAV_ERR_NEW_MALLOC; - goto END; + goto RETURN; } av->tox = tox; @@ -174,7 +174,7 @@ ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error) if (av->msi == nullptr) { pthread_mutex_destroy(av->mutex); rc = TOXAV_ERR_NEW_MALLOC; - goto END; + goto RETURN; } av->interval = 200; @@ -187,7 +187,7 @@ ToxAV *toxav_new(Tox *tox, TOXAV_ERR_NEW *error) msi_register_callback(av->msi, callback_error, MSI_ON_PEERTIMEOUT); msi_register_callback(av->msi, callback_capabilites, MSI_ON_CAPABILITIES); -END: +RETURN: if (error) { *error = rc; @@ -268,7 +268,7 @@ void toxav_iterate(ToxAV *av) if (i->msi_call->self_capabilities & MSI_CAP_R_VIDEO && i->msi_call->peer_capabilities & MSI_CAP_S_VIDEO) { - rc = min_u32(i->video->lcfd, (uint32_t) rc); + rc = min_u32(i->video->lcfd, rc); } uint32_t fid = i->friend_number; @@ -295,9 +295,9 @@ void toxav_iterate(ToxAV *av) } } bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, - TOXAV_ERR_CALL *error) + Toxav_Err_Call *error) { - TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK; + Toxav_Err_Call rc = TOXAV_ERR_CALL_OK; ToxAVCall *call; pthread_mutex_lock(av->mutex); @@ -305,13 +305,13 @@ bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate)) || (video_bit_rate && video_bit_rate_invalid(video_bit_rate))) { rc = TOXAV_ERR_CALL_INVALID_BIT_RATE; - goto END; + goto RETURN; } call = call_new(av, friend_number, &rc); if (call == nullptr) { - goto END; + goto RETURN; } call->audio_bit_rate = audio_bit_rate; @@ -325,12 +325,12 @@ bool toxav_call(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint if (msi_invite(av->msi, &call->msi_call, friend_number, call->previous_self_capabilities) != 0) { call_remove(call); rc = TOXAV_ERR_CALL_SYNC; - goto END; + goto RETURN; } call->msi_call->av_call = call; -END: +RETURN: pthread_mutex_unlock(av->mutex); if (error) { @@ -347,35 +347,35 @@ void toxav_callback_call(ToxAV *av, toxav_call_cb *callback, void *user_data) pthread_mutex_unlock(av->mutex); } bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, uint32_t video_bit_rate, - TOXAV_ERR_ANSWER *error) + Toxav_Err_Answer *error) { pthread_mutex_lock(av->mutex); - TOXAV_ERR_ANSWER rc = TOXAV_ERR_ANSWER_OK; + Toxav_Err_Answer rc = TOXAV_ERR_ANSWER_OK; ToxAVCall *call; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_ANSWER_FRIEND_NOT_FOUND; - goto END; + goto RETURN; } if ((audio_bit_rate && audio_bit_rate_invalid(audio_bit_rate)) || (video_bit_rate && video_bit_rate_invalid(video_bit_rate)) ) { rc = TOXAV_ERR_ANSWER_INVALID_BIT_RATE; - goto END; + goto RETURN; } call = call_get(av, friend_number); if (call == nullptr) { rc = TOXAV_ERR_ANSWER_FRIEND_NOT_CALLING; - goto END; + goto RETURN; } if (!call_prepare_transmission(call)) { rc = TOXAV_ERR_ANSWER_CODEC_INITIALIZATION; - goto END; + goto RETURN; } call->audio_bit_rate = audio_bit_rate; @@ -390,7 +390,7 @@ bool toxav_answer(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, ui rc = TOXAV_ERR_ANSWER_SYNC; } -END: +RETURN: pthread_mutex_unlock(av->mutex); if (error) { @@ -406,22 +406,22 @@ void toxav_callback_call_state(ToxAV *av, toxav_call_state_cb *callback, void *u av->scb_user_data = user_data; pthread_mutex_unlock(av->mutex); } -bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL control, TOXAV_ERR_CALL_CONTROL *error) +bool toxav_call_control(ToxAV *av, uint32_t friend_number, Toxav_Call_Control control, Toxav_Err_Call_Control *error) { pthread_mutex_lock(av->mutex); - TOXAV_ERR_CALL_CONTROL rc = TOXAV_ERR_CALL_CONTROL_OK; + Toxav_Err_Call_Control rc = TOXAV_ERR_CALL_CONTROL_OK; ToxAVCall *call; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_FOUND; - goto END; + goto RETURN; } call = call_get(av, friend_number); if (call == nullptr || (!call->active && control != TOXAV_CALL_CONTROL_CANCEL)) { rc = TOXAV_ERR_CALL_CONTROL_FRIEND_NOT_IN_CALL; - goto END; + goto RETURN; } switch (control) { @@ -433,14 +433,14 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co if (msi_change_capabilities(call->msi_call, call->previous_self_capabilities) == -1) { rc = TOXAV_ERR_CALL_CONTROL_SYNC; - goto END; + goto RETURN; } rtp_allow_receiving(call->audio_rtp); rtp_allow_receiving(call->video_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; - goto END; + goto RETURN; } } break; @@ -452,14 +452,14 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co if (msi_change_capabilities(call->msi_call, 0) == -1) { rc = TOXAV_ERR_CALL_CONTROL_SYNC; - goto END; + goto RETURN; } rtp_stop_receiving(call->audio_rtp); rtp_stop_receiving(call->video_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; - goto END; + goto RETURN; } } break; @@ -471,7 +471,7 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co if (msi_hangup(call->msi_call) != 0) { rc = TOXAV_ERR_CALL_CONTROL_SYNC; pthread_mutex_unlock(call->mutex); - goto END; + goto RETURN; } call->msi_call = nullptr; @@ -488,13 +488,13 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co if (msi_change_capabilities(call->msi_call, call-> msi_call->self_capabilities ^ MSI_CAP_R_AUDIO) == -1) { rc = TOXAV_ERR_CALL_CONTROL_SYNC; - goto END; + goto RETURN; } rtp_stop_receiving(call->audio_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; - goto END; + goto RETURN; } } break; @@ -504,13 +504,13 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co if (msi_change_capabilities(call->msi_call, call-> msi_call->self_capabilities | MSI_CAP_R_AUDIO) == -1) { rc = TOXAV_ERR_CALL_CONTROL_SYNC; - goto END; + goto RETURN; } rtp_allow_receiving(call->audio_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; - goto END; + goto RETURN; } } break; @@ -520,13 +520,13 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co if (msi_change_capabilities(call->msi_call, call-> msi_call->self_capabilities ^ MSI_CAP_R_VIDEO) == -1) { rc = TOXAV_ERR_CALL_CONTROL_SYNC; - goto END; + goto RETURN; } rtp_stop_receiving(call->video_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; - goto END; + goto RETURN; } } break; @@ -536,19 +536,19 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co if (msi_change_capabilities(call->msi_call, call-> msi_call->self_capabilities | MSI_CAP_R_VIDEO) == -1) { rc = TOXAV_ERR_CALL_CONTROL_SYNC; - goto END; + goto RETURN; } rtp_allow_receiving(call->video_rtp); } else { rc = TOXAV_ERR_CALL_CONTROL_INVALID_TRANSITION; - goto END; + goto RETURN; } } break; } -END: +RETURN: pthread_mutex_unlock(av->mutex); if (error) { @@ -558,19 +558,19 @@ bool toxav_call_control(ToxAV *av, uint32_t friend_number, TOXAV_CALL_CONTROL co return rc == TOXAV_ERR_CALL_CONTROL_OK; } bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_bit_rate, - TOXAV_ERR_BIT_RATE_SET *error) + Toxav_Err_Bit_Rate_Set *error) { - TOXAV_ERR_BIT_RATE_SET rc = TOXAV_ERR_BIT_RATE_SET_OK; + Toxav_Err_Bit_Rate_Set rc = TOXAV_ERR_BIT_RATE_SET_OK; ToxAVCall *call; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND; - goto END; + goto RETURN; } if (audio_bit_rate > 0 && audio_bit_rate_invalid(audio_bit_rate)) { rc = TOXAV_ERR_BIT_RATE_SET_INVALID_BIT_RATE; - goto END; + goto RETURN; } pthread_mutex_lock(av->mutex); @@ -579,7 +579,7 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ if (call == nullptr || !call->active || call->msi_call->state != MSI_CALL_ACTIVE) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL; - goto END; + goto RETURN; } LOGGER_DEBUG(av->m->log, "Setting new audio bitrate to: %d", audio_bit_rate); @@ -593,7 +593,7 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ self_capabilities ^ MSI_CAP_S_AUDIO) != 0) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_BIT_RATE_SET_SYNC; - goto END; + goto RETURN; } /* Audio sending is turned off; notify peer */ @@ -610,7 +610,7 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ pthread_mutex_unlock(call->mutex); pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_BIT_RATE_SET_SYNC; - goto END; + goto RETURN; } } else { LOGGER_DEBUG(av->m->log, "Set new audio bit rate %d", audio_bit_rate); @@ -621,7 +621,7 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ } pthread_mutex_unlock(av->mutex); -END: +RETURN: if (error) { *error = rc; @@ -630,19 +630,19 @@ bool toxav_audio_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t audio_ return rc == TOXAV_ERR_BIT_RATE_SET_OK; } bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_bit_rate, - TOXAV_ERR_BIT_RATE_SET *error) + Toxav_Err_Bit_Rate_Set *error) { - TOXAV_ERR_BIT_RATE_SET rc = TOXAV_ERR_BIT_RATE_SET_OK; + Toxav_Err_Bit_Rate_Set rc = TOXAV_ERR_BIT_RATE_SET_OK; ToxAVCall *call; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_FOUND; - goto END; + goto RETURN; } if (video_bit_rate > 0 && video_bit_rate_invalid(video_bit_rate)) { rc = TOXAV_ERR_BIT_RATE_SET_INVALID_BIT_RATE; - goto END; + goto RETURN; } pthread_mutex_lock(av->mutex); @@ -651,7 +651,7 @@ bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_ if (call == nullptr || !call->active || call->msi_call->state != MSI_CALL_ACTIVE) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_BIT_RATE_SET_FRIEND_NOT_IN_CALL; - goto END; + goto RETURN; } LOGGER_DEBUG(av->m->log, "Setting new video bitrate to: %d", video_bit_rate); @@ -666,7 +666,7 @@ bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_ self_capabilities ^ MSI_CAP_S_VIDEO) != 0) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_BIT_RATE_SET_SYNC; - goto END; + goto RETURN; } call->video_bit_rate = 0; @@ -682,7 +682,7 @@ bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_ pthread_mutex_unlock(call->mutex); pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_BIT_RATE_SET_SYNC; - goto END; + goto RETURN; } } else { LOGGER_DEBUG(av->m->log, "Set new video bit rate %d", video_bit_rate); @@ -693,7 +693,7 @@ bool toxav_video_set_bit_rate(ToxAV *av, uint32_t friend_number, uint32_t video_ } pthread_mutex_unlock(av->mutex); -END: +RETURN: if (error) { *error = rc; @@ -716,19 +716,19 @@ void toxav_callback_video_bit_rate(ToxAV *av, toxav_video_bit_rate_cb *callback, pthread_mutex_unlock(av->mutex); } 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) + uint8_t channels, uint32_t sampling_rate, Toxav_Err_Send_Frame *error) { - TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; + Toxav_Err_Send_Frame rc = TOXAV_ERR_SEND_FRAME_OK; ToxAVCall *call; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND; - goto END; + goto RETURN; } if (pthread_mutex_trylock(av->mutex) != 0) { rc = TOXAV_ERR_SEND_FRAME_SYNC; - goto END; + goto RETURN; } call = call_get(av, friend_number); @@ -736,7 +736,7 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc if (call == nullptr || !call->active || call->msi_call->state != MSI_CALL_ACTIVE) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; - goto END; + goto RETURN; } if (call->audio_bit_rate == 0 || @@ -744,7 +744,7 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc !(call->msi_call->peer_capabilities & MSI_CAP_R_AUDIO)) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED; - goto END; + goto RETURN; } pthread_mutex_lock(call->mutex_audio); @@ -753,20 +753,20 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc if (pcm == nullptr) { pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_NULL; - goto END; + goto RETURN; } if (channels > 2) { pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_INVALID; - goto END; + goto RETURN; } { /* Encode and send */ if (ac_reconfigure_encoder(call->audio, call->audio_bit_rate * 1000, sampling_rate, channels) != 0) { pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_INVALID; - goto END; + goto RETURN; } VLA(uint8_t, dest, sample_count + sizeof(sampling_rate)); /* This is more than enough always */ @@ -780,7 +780,7 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc LOGGER_WARNING(av->m->log, "Failed to encode frame %s", opus_strerror(vrc)); pthread_mutex_unlock(call->mutex_audio); rc = TOXAV_ERR_SEND_FRAME_INVALID; - goto END; + goto RETURN; } if (rtp_send_data(call->audio_rtp, dest, vrc + sizeof(sampling_rate), false, av->m->log) != 0) { @@ -791,7 +791,7 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc pthread_mutex_unlock(call->mutex_audio); -END: +RETURN: if (error) { *error = rc; @@ -800,22 +800,60 @@ bool toxav_audio_send_frame(ToxAV *av, uint32_t friend_number, const int16_t *pc return rc == TOXAV_ERR_SEND_FRAME_OK; } +static Toxav_Err_Send_Frame send_frames(const Logger *log, ToxAVCall *call) +{ + vpx_codec_iter_t iter = nullptr; + + for (const vpx_codec_cx_pkt_t *pkt = vpx_codec_get_cx_data(call->video->encoder, &iter); + pkt != nullptr; + pkt = vpx_codec_get_cx_data(call->video->encoder, &iter)) { + if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) { + continue; + } + + const bool is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; + + // https://www.webmproject.org/docs/webm-sdk/structvpx__codec__cx__pkt.html + // pkt->data.frame.sz -> size_t + const uint32_t frame_length_in_bytes = pkt->data.frame.sz; + + const int res = rtp_send_data( + call->video_rtp, + (const uint8_t *)pkt->data.frame.buf, + frame_length_in_bytes, + is_keyframe, + log); + + LOGGER_DEBUG(log, "+ _sending_FRAME_TYPE_==%s bytes=%d frame_len=%d", is_keyframe ? "K" : ".", + (int)pkt->data.frame.sz, (int)frame_length_in_bytes); + const uint8_t *const buf = (const uint8_t *)pkt->data.frame.buf; + LOGGER_DEBUG(log, "+ _sending_FRAME_ b0=%d b1=%d", buf[0], buf[1]); + + if (res < 0) { + LOGGER_WARNING(log, "Could not send video frame: %s", strerror(errno)); + return TOXAV_ERR_SEND_FRAME_RTP_FAILED; + } + } + + return TOXAV_ERR_SEND_FRAME_OK; +} + 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, TOXAV_ERR_SEND_FRAME *error) + const uint8_t *u, const uint8_t *v, Toxav_Err_Send_Frame *error) { - TOXAV_ERR_SEND_FRAME rc = TOXAV_ERR_SEND_FRAME_OK; + Toxav_Err_Send_Frame rc = TOXAV_ERR_SEND_FRAME_OK; ToxAVCall *call; int vpx_encode_flags = 0; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_FOUND; - goto END; + goto RETURN; } if (pthread_mutex_trylock(av->mutex) != 0) { rc = TOXAV_ERR_SEND_FRAME_SYNC; - goto END; + goto RETURN; } call = call_get(av, friend_number); @@ -823,7 +861,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u if (call == nullptr || !call->active || call->msi_call->state != MSI_CALL_ACTIVE) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_SEND_FRAME_FRIEND_NOT_IN_CALL; - goto END; + goto RETURN; } if (call->video_bit_rate == 0 || @@ -831,7 +869,7 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u !(call->msi_call->peer_capabilities & MSI_CAP_R_VIDEO)) { pthread_mutex_unlock(av->mutex); rc = TOXAV_ERR_SEND_FRAME_PAYLOAD_TYPE_DISABLED; - goto END; + goto RETURN; } pthread_mutex_lock(call->mutex_video); @@ -840,13 +878,13 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u if (y == nullptr || u == nullptr || v == nullptr) { pthread_mutex_unlock(call->mutex_video); rc = TOXAV_ERR_SEND_FRAME_NULL; - goto END; + goto RETURN; } if (vc_reconfigure_encoder(call->video, call->video_bit_rate * 1000, width, height, -1) != 0) { pthread_mutex_unlock(call->mutex_video); rc = TOXAV_ERR_SEND_FRAME_INVALID; - goto END; + goto RETURN; } if (call->video_rtp->ssrc < VIDEO_SEND_X_KEYFRAMES_FIRST) { @@ -854,20 +892,23 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u vpx_encode_flags = VPX_EFLAG_FORCE_KF; LOGGER_INFO(av->m->log, "I_FRAME_FLAG:%d only-i-frame mode", call->video_rtp->ssrc); - call->video_rtp->ssrc++; + ++call->video_rtp->ssrc; } else if (call->video_rtp->ssrc == VIDEO_SEND_X_KEYFRAMES_FIRST) { // normal keyframe placement vpx_encode_flags = 0; LOGGER_INFO(av->m->log, "I_FRAME_FLAG:%d normal mode", call->video_rtp->ssrc); - call->video_rtp->ssrc++; + ++call->video_rtp->ssrc; } // we start with I-frames (full frames) and then switch to normal mode later { /* Encode */ vpx_image_t img; - img.w = img.h = img.d_w = img.d_h = 0; + img.w = 0; + img.h = 0; + img.d_w = 0; + img.d_h = 0; vpx_img_alloc(&img, VPX_IMG_FMT_I420, width, height, 0); /* I420 "It comprises an NxM Y plane followed by (N/2)x(M/2) V and U planes." @@ -886,49 +927,17 @@ bool toxav_video_send_frame(ToxAV *av, uint32_t friend_number, uint16_t width, u pthread_mutex_unlock(call->mutex_video); LOGGER_ERROR(av->m->log, "Could not encode video frame: %s\n", vpx_codec_err_to_string(vrc)); rc = TOXAV_ERR_SEND_FRAME_INVALID; - goto END; + goto RETURN; } } ++call->video->frame_counter; - { /* Send frames */ - vpx_codec_iter_t iter = nullptr; - const vpx_codec_cx_pkt_t *pkt; - - while ((pkt = vpx_codec_get_cx_data(call->video->encoder, &iter)) != nullptr) { - if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) { - const bool is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; - - // https://www.webmproject.org/docs/webm-sdk/structvpx__codec__cx__pkt.html - // pkt->data.frame.sz -> size_t - const uint32_t frame_length_in_bytes = pkt->data.frame.sz; - - const int res = rtp_send_data( - call->video_rtp, - (const uint8_t *)pkt->data.frame.buf, - frame_length_in_bytes, - is_keyframe, - av->m->log); - - LOGGER_DEBUG(av->m->log, "+ _sending_FRAME_TYPE_==%s bytes=%d frame_len=%d", is_keyframe ? "K" : ".", - (int)pkt->data.frame.sz, (int)frame_length_in_bytes); - LOGGER_DEBUG(av->m->log, "+ _sending_FRAME_ b0=%d b1=%d", ((const uint8_t *)pkt->data.frame.buf)[0], - ((const uint8_t *)pkt->data.frame.buf)[1]); - - if (res < 0) { - pthread_mutex_unlock(call->mutex_video); - LOGGER_WARNING(av->m->log, "Could not send video frame: %s", strerror(errno)); - rc = TOXAV_ERR_SEND_FRAME_RTP_FAILED; - goto END; - } - } - } - } + rc = send_frames(av->m->log, call); pthread_mutex_unlock(call->mutex_video); -END: +RETURN: if (error) { *error = rc; @@ -986,9 +995,9 @@ void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *u return; } - (*call->av->vbcb)(call->av, friend_number, - call->video_bit_rate - (call->video_bit_rate * loss), - call->av->vbcb_user_data); + call->av->vbcb(call->av, friend_number, + call->video_bit_rate - (call->video_bit_rate * loss), + call->av->vbcb_user_data); } else if (call->audio_bit_rate) { if (!call->av->abcb) { pthread_mutex_unlock(call->av->mutex); @@ -996,9 +1005,9 @@ void callback_bwc(BWController *bwc, uint32_t friend_number, float loss, void *u return; } - (*call->av->abcb)(call->av, friend_number, - call->audio_bit_rate - (call->audio_bit_rate * loss), - call->av->abcb_user_data); + call->av->abcb(call->av, friend_number, + call->audio_bit_rate - (call->audio_bit_rate * loss), + call->av->abcb_user_data); } pthread_mutex_unlock(call->av->mutex); @@ -1067,8 +1076,8 @@ int callback_end(void *toxav_inst, MSICall *call) invoke_call_state_callback(toxav, call->friend_number, TOXAV_FRIEND_CALL_STATE_FINISHED); if (call->av_call) { - call_kill_transmission((ToxAVCall *)call->av_call); - call_remove((ToxAVCall *)call->av_call); + call_kill_transmission(call->av_call); + call_remove(call->av_call); } pthread_mutex_unlock(toxav->mutex); @@ -1082,8 +1091,8 @@ int callback_error(void *toxav_inst, MSICall *call) invoke_call_state_callback(toxav, call->friend_number, TOXAV_FRIEND_CALL_STATE_ERROR); if (call->av_call) { - call_kill_transmission((ToxAVCall *)call->av_call); - call_remove((ToxAVCall *)call->av_call); + call_kill_transmission(call->av_call); + call_remove(call->av_call); } pthread_mutex_unlock(toxav->mutex); @@ -1095,15 +1104,15 @@ int callback_capabilites(void *toxav_inst, MSICall *call) pthread_mutex_lock(toxav->mutex); if (call->peer_capabilities & MSI_CAP_S_AUDIO) { - rtp_allow_receiving(((ToxAVCall *)call->av_call)->audio_rtp); + rtp_allow_receiving(call->av_call->audio_rtp); } else { - rtp_stop_receiving(((ToxAVCall *)call->av_call)->audio_rtp); + rtp_stop_receiving(call->av_call->audio_rtp); } if (call->peer_capabilities & MSI_CAP_S_VIDEO) { - rtp_allow_receiving(((ToxAVCall *)call->av_call)->video_rtp); + rtp_allow_receiving(call->av_call->video_rtp); } else { - rtp_stop_receiving(((ToxAVCall *)call->av_call)->video_rtp); + rtp_stop_receiving(call->av_call->video_rtp); } invoke_call_state_callback(toxav, call->friend_number, call->peer_capabilities); @@ -1140,32 +1149,32 @@ bool invoke_call_state_callback(ToxAV *av, uint32_t friend_number, uint32_t stat return true; } -ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, TOXAV_ERR_CALL *error) +ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, Toxav_Err_Call *error) { /* Assumes mutex locked */ - TOXAV_ERR_CALL rc = TOXAV_ERR_CALL_OK; + Toxav_Err_Call rc = TOXAV_ERR_CALL_OK; ToxAVCall *call = nullptr; if (m_friend_exists(av->m, friend_number) == 0) { rc = TOXAV_ERR_CALL_FRIEND_NOT_FOUND; - goto END; + goto RETURN; } if (m_get_friend_connectionstatus(av->m, friend_number) < 1) { rc = TOXAV_ERR_CALL_FRIEND_NOT_CONNECTED; - goto END; + goto RETURN; } if (call_get(av, friend_number) != nullptr) { rc = TOXAV_ERR_CALL_FRIEND_ALREADY_IN_CALL; - goto END; + goto RETURN; } call = (ToxAVCall *)calloc(sizeof(ToxAVCall), 1); if (call == nullptr) { rc = TOXAV_ERR_CALL_MALLOC; - goto END; + goto RETURN; } call->av = av; @@ -1178,10 +1187,11 @@ ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, TOXAV_ERR_CALL *error) free(call); call = nullptr; rc = TOXAV_ERR_CALL_MALLOC; - goto END; + goto RETURN; } - av->calls_tail = av->calls_head = friend_number; + av->calls_tail = friend_number; + av->calls_head = friend_number; } else if (av->calls_tail < friend_number) { /* Appending */ ToxAVCall **tmp = (ToxAVCall **)realloc(av->calls, sizeof(ToxAVCall *) * (friend_number + 1)); @@ -1189,15 +1199,13 @@ ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, TOXAV_ERR_CALL *error) free(call); call = nullptr; rc = TOXAV_ERR_CALL_MALLOC; - goto END; + goto RETURN; } av->calls = tmp; /* Set fields in between to null */ - uint32_t i = av->calls_tail + 1; - - for (; i < friend_number; i ++) { + for (uint32_t i = av->calls_tail + 1; i < friend_number; ++i) { av->calls[i] = nullptr; } @@ -1213,7 +1221,7 @@ ToxAVCall *call_new(ToxAV *av, uint32_t friend_number, TOXAV_ERR_CALL *error) av->calls[friend_number] = call; -END: +RETURN: if (error) { *error = rc; @@ -1273,7 +1281,8 @@ ToxAVCall *call_remove(ToxAVCall *call) return next; CLEAR: - av->calls_head = av->calls_tail = 0; + av->calls_head = 0; + av->calls_tail = 0; free(av->calls); av->calls = nullptr; @@ -1327,7 +1336,7 @@ bool call_prepare_transmission(ToxAVCall *call) call->audio, ac_queue_message); if (!call->audio_rtp) { - LOGGER_ERROR(av->m->log, "Failed to create audio rtp session");; + LOGGER_ERROR(av->m->log, "Failed to create audio rtp session"); goto FAILURE; } } diff --git a/toxav/toxav.h b/toxav/toxav.h index 911d6b499c..5b25fdebf4 100644 --- a/toxav/toxav.h +++ b/toxav/toxav.h @@ -733,6 +733,10 @@ void toxav_callback_video_receive_frame(ToxAV *av, toxav_video_receive_frame_cb /** * NOTE Compatibility with old toxav group calls. TODO(iphydf): remove + * + * TODO(iphydf): Use proper new API guidelines for these. E.g. don't use inline + * function types, don't have per-callback userdata, especially don't have one + * userdata per group. */ /* Create a new toxav group. * @@ -744,9 +748,9 @@ void toxav_callback_video_receive_frame(ToxAV *av, toxav_video_receive_frame_cb * * Note that total size of pcm in bytes is equal to (samples * channels * sizeof(int16_t)). */ -int toxav_add_av_groupchat(Tox *tox, void (*audio_callback)(void *, uint32_t, uint32_t, const int16_t *, unsigned int, - uint8_t, - uint32_t, void *), void *userdata); +int toxav_add_av_groupchat(Tox *tox, + void (*audio_callback)(void *, uint32_t, uint32_t, const int16_t *, unsigned int, uint8_t, uint32_t, void *), + void *userdata); /* Join a AV group (you need to have been invited first.) * @@ -781,4 +785,16 @@ int toxav_group_send_audio(Tox *tox, uint32_t groupnumber, const int16_t *pcm, u #ifdef __cplusplus } #endif + +typedef void toxav_group_audio_cb(Tox *tox, uint32_t groupnumber, uint32_t peernumber, const int16_t *pcm, + uint32_t samples, uint8_t channels, uint32_t sample_rate, void *user_data); + +typedef TOXAV_ERR_CALL Toxav_Err_Call; +typedef TOXAV_ERR_NEW Toxav_Err_New; +typedef TOXAV_ERR_ANSWER Toxav_Err_Answer; +typedef TOXAV_ERR_CALL_CONTROL Toxav_Err_Call_Control; +typedef TOXAV_ERR_BIT_RATE_SET Toxav_Err_Bit_Rate_Set; +typedef TOXAV_ERR_SEND_FRAME Toxav_Err_Send_Frame; +typedef TOXAV_CALL_CONTROL Toxav_Call_Control; + #endif /* TOXAV_H */