/** * @brief Call this at the end of the transmission. * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) { CallSpecific *call = &av->calls[call_index]; if ( call->crtps[audio_index] && -1 == rtp_terminate_session(call->crtps[audio_index], av->messenger) ) { /*fprintf(stderr, "Error while terminating audio RTP session!\n");*/ return ErrorTerminatingAudioRtp; } if ( call->crtps[video_index] && -1 == rtp_terminate_session(call->crtps[video_index], av->messenger) ) { /*fprintf(stderr, "Error while terminating video RTP session!\n");*/ return ErrorTerminatingVideoRtp; } call->crtps[audio_index] = NULL; call->crtps[video_index] = NULL; if ( call->j_buf ) { terminate_queue(call->j_buf); call->j_buf = NULL; LOGGER_DEBUG("Terminated j queue"); } else LOGGER_DEBUG("No j queue"); if ( call->cs ) { codec_terminate_session(call->cs); call->cs = NULL; LOGGER_DEBUG("Terminated codec session"); } else LOGGER_DEBUG("No codec session"); return ErrorNone; }
/** * @brief Remove A/V session. * * @param av Handler. * @return void */ void toxav_kill ( ToxAv *av ) { msi_terminate_session(av->msi_session); if ( av->rtp_sessions[audio_index] ) { rtp_terminate_session(av->rtp_sessions[audio_index], av->msi_session->messenger_handle); } if ( av->rtp_sessions[video_index] ) { rtp_terminate_session(av->rtp_sessions[video_index], av->msi_session->messenger_handle); } codec_terminate_session(av->cs); free(av); }
/** * @brief Remove A/V session. * * @param av Handler. * @return void */ void toxav_kill ( ToxAv *av ) { uint32_t i; for (i = 0; i < av->max_calls; i ++) { if ( av->calls[i].crtps[audio_index] ) rtp_terminate_session(av->calls[i].crtps[audio_index], av->msi_session->messenger_handle); if ( av->calls[i].crtps[video_index] ) rtp_terminate_session(av->calls[i].crtps[video_index], av->msi_session->messenger_handle); if ( av->calls[i].j_buf ) terminate_queue(av->calls[i].j_buf); if ( av->calls[i].cs ) codec_terminate_session(av->calls[i].cs); } msi_terminate_session(av->msi_session); free(av->calls); free(av); }
/** * @brief Call this at the end of the transmission. * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) { if (cii(call_index, av->msi_session) || !av->calls[call_index].call_active) { LOGGER_WARNING("Action on inactive call: %d", call_index); return ErrorNoCall; } CallSpecific *call = &av->calls[call_index]; call->call_active = 0; if ( call->crtps[audio_index] && -1 == rtp_terminate_session(call->crtps[audio_index], av->messenger) ) { LOGGER_ERROR("Error while terminating audio RTP session!\n"); /*return ErrorTerminatingAudioRtp;*/ } else call->crtps[audio_index] = NULL; if ( call->crtps[video_index] && -1 == rtp_terminate_session(call->crtps[video_index], av->messenger) ) { LOGGER_ERROR("Error while terminating video RTP session!\n"); /*return ErrorTerminatingVideoRtp;*/ } else call->crtps[video_index] = NULL; if ( call->j_buf ) { terminate_queue(call->j_buf); call->j_buf = NULL; LOGGER_DEBUG("Terminated j queue"); } else LOGGER_DEBUG("No j queue"); if ( call->cs ) { codec_terminate_session(call->cs); call->cs = NULL; LOGGER_DEBUG("Terminated codec session"); } else LOGGER_DEBUG("No codec session"); return ErrorNone; }
/** * @brief Call this at the end of the transmission. * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ int toxav_kill_transmission ( ToxAv *av, int32_t call_index ) { if (cii(call_index, av->msi_session)) { LOGGER_WARNING("Invalid call index: %d", call_index); return ErrorNoCall; } CallSpecific *call = &av->calls[call_index]; pthread_mutex_lock(&call->mutex); if (!call->call_active) { pthread_mutex_unlock(&call->mutex); LOGGER_WARNING("Action on inactive call: %d", call_index); return ErrorNoCall; } call->call_active = 0; rtp_terminate_session(call->crtps[audio_index], av->messenger); call->crtps[audio_index] = NULL; rtp_terminate_session(call->crtps[video_index], av->messenger); call->crtps[video_index] = NULL; terminate_queue(call->j_buf); call->j_buf = NULL; int i; DECODE_PACKET *p; call->exit = 1; pthread_mutex_lock(&call->decode_cond_mutex); pthread_cond_signal(&call->decode_cond); pthread_cond_wait(&call->decode_cond, &call->decode_cond_mutex); pthread_mutex_unlock(&call->decode_cond_mutex); pthread_mutex_destroy(&call->decode_cond_mutex); pthread_cond_destroy(&call->decode_cond); for (i = 0; i != VIDEO_DECODE_QUEUE_SIZE; i++) { p = call->video_decode_queue[i]; call->video_decode_queue[i] = NULL; if (p) { free(p); } } for (i = 0; i != AUDIO_DECODE_QUEUE_SIZE; i++) { p = call->audio_decode_queue[i]; call->audio_decode_queue[i] = NULL; if (p) { free(p); } } codec_terminate_session(call->cs); call->cs = NULL; pthread_mutex_unlock(&call->mutex); pthread_mutex_destroy(&call->mutex); memset(call, 0, sizeof(CallSpecific)); return ErrorNone; }
/** * @brief Must be call before any RTP transmission occurs. * * @param av Handler. * @return int * @retval 0 Success. * @retval ToxAvError On error. */ int toxav_prepare_transmission ( ToxAv *av, int32_t call_index, uint32_t jbuf_capacity, uint32_t VAD_treshold, int support_video ) { if ( !av->msi_session || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] || !av->msi_session->calls[call_index]->csettings_peer || av->calls[call_index].call_active) { LOGGER_ERROR("Error while starting RTP session: invalid call!\n"); return ErrorInternal; } CallSpecific *call = &av->calls[call_index]; call->crtps[audio_index] = rtp_init_session(type_audio, av->messenger, av->msi_session->calls[call_index]->peers[0]); if ( !call->crtps[audio_index] ) { LOGGER_ERROR("Error while starting audio RTP session!\n"); return ErrorInternal; } call->crtps[audio_index]->call_index = call_index; call->crtps[audio_index]->av = av; if ( support_video ) { call->crtps[video_index] = rtp_init_session(type_video, av->messenger, av->msi_session->calls[call_index]->peers[0]); if ( !call->crtps[video_index] ) { LOGGER_ERROR("Error while starting video RTP session!\n"); goto error; } call->crtps[video_index]->call_index = call_index; call->crtps[video_index]->av = av; call->frame_limit = 0; call->frame_id = 0; call->frame_outid = 0; call->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1); if (!call->frame_buf) { LOGGER_WARNING("Frame buffer allocation failed!"); goto error; } } if ( !(call->j_buf = create_queue(jbuf_capacity)) ) { LOGGER_WARNING("Jitter buffer creaton failed!"); goto error; } ToxAvCSettings csettings_peer = toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_peer[0]); ToxAvCSettings csettings_local = toxavcsettings_cast(&av->msi_session->calls[call_index]->csettings_local); LOGGER_DEBUG( "Type: %u \n" "Video bitrate: %u \n" "Video height: %u \n" "Video width: %u \n" "Audio bitrate: %u \n" "Audio framedur: %u \n" "Audio sample rate: %u \n" "Audio channels: %u \n", csettings_peer.call_type, csettings_peer.video_bitrate, csettings_peer.max_video_height, csettings_peer.max_video_width, csettings_peer.audio_bitrate, csettings_peer.audio_frame_duration, csettings_peer.audio_sample_rate, csettings_peer.audio_channels ); if ( (call->cs = codec_init_session(csettings_local.audio_bitrate, csettings_local.audio_frame_duration, csettings_local.audio_sample_rate, csettings_local.audio_channels, csettings_peer.audio_channels, VAD_treshold, csettings_local.max_video_width, csettings_local.max_video_height, csettings_local.video_bitrate) )) { if ( pthread_mutex_init(&call->mutex, NULL) != 0 ) goto error; //todo: add error checks pthread_mutex_init(&call->decode_cond_mutex, NULL); pthread_cond_init(&call->decode_cond, NULL); void **arg = malloc(2 * sizeof(void *)); arg[0] = av; arg[1] = call; pthread_t temp; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 1 << 18); pthread_create(&temp, &attr, toxav_decoding, arg); pthread_attr_destroy(&attr); LOGGER_WARNING("Got here"); call->call_active = 1; return ErrorNone; } error: rtp_terminate_session(call->crtps[audio_index], av->messenger); rtp_terminate_session(call->crtps[video_index], av->messenger); free(call->frame_buf); terminate_queue(call->j_buf); codec_terminate_session(call->cs); return ErrorInternal; }