/** * @brief Start new A/V session. There can only be one session at the time. If you register more * it will result in undefined behaviour. * * @param messenger The messenger handle. * @param userdata The agent handling A/V session (i.e. phone). * @param video_width Width of video frame. * @param video_height Height of video frame. * @return ToxAv* * @retval NULL On error. */ ToxAv *toxav_new( Tox* messenger, ToxAvCodecSettings* codec_settings) { ToxAv *av = calloc ( sizeof(ToxAv), 1); if (av == NULL) return NULL; av->messenger = (Messenger *)messenger; av->msi_session = msi_init_session(av->messenger); av->msi_session->agent_handler = av; av->rtp_sessions[0] = av->rtp_sessions [1] = NULL; /* NOTE: This should be user defined or? */ av->j_buf = create_queue(codec_settings->jbuf_capacity); av->cs = codec_init_session(codec_settings->audio_bitrate, codec_settings->audio_frame_duration, codec_settings->audio_sample_rate, codec_settings->audio_channels, codec_settings->video_width, codec_settings->video_height, codec_settings->video_bitrate); return av; }
/** * @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, ToxAvCodecSettings *codec_settings, int support_video ) { if ( !av->msi_session || av->msi_session->max_calls <= call_index || !av->msi_session->calls[call_index] ) { /*fprintf(stderr, "Error while starting audio 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], av->msi_session->calls[call_index]->key_peer, av->msi_session->calls[call_index]->key_local, av->msi_session->calls[call_index]->nonce_peer, av->msi_session->calls[call_index]->nonce_local); if ( !call->crtps[audio_index] ) { /*fprintf(stderr, "Error while starting audio RTP session!\n");*/ return ErrorStartingAudioRtp; } if ( support_video ) { call->crtps[video_index] = rtp_init_session ( type_video, av->messenger, av->msi_session->calls[call_index]->peers[0], av->msi_session->calls[call_index]->key_peer, av->msi_session->calls[call_index]->key_local, av->msi_session->calls[call_index]->nonce_peer, av->msi_session->calls[call_index]->nonce_local); if ( !call->crtps[video_index] ) { /*fprintf(stderr, "Error while starting video RTP session!\n");*/ return ErrorStartingVideoRtp; } } if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) return ErrorInternal; call->cs = codec_init_session(codec_settings->audio_bitrate, codec_settings->audio_frame_duration, codec_settings->audio_sample_rate, codec_settings->audio_channels, codec_settings->video_width, codec_settings->video_height, codec_settings->video_bitrate); return call->cs ? ErrorNone : ErrorInternal; }
/** * @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; }
/** * @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, ToxAvCodecSettings *codec_settings, int support_video ) { if ( !av->msi_session || cii(call_index, av->msi_session) || !av->msi_session->calls[call_index] || 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 ErrorStartingAudioRtp; } 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"); rtp_terminate_session(call->crtps[audio_index], av->messenger); return ErrorStartingVideoRtp; } call->frame_limit = 0; call->frame_id = 0; call->frame_outid = 0; call->frame_buf = calloc(MAX_VIDEOFRAME_SIZE, 1); if (!call->frame_buf) { rtp_terminate_session(call->crtps[audio_index], av->messenger); rtp_terminate_session(call->crtps[video_index], av->messenger); LOGGER_WARNING("Frame buffer allocation failed!"); return ErrorInternal; } } if ( !(call->j_buf = create_queue(codec_settings->jbuf_capacity)) ) { rtp_terminate_session(call->crtps[audio_index], av->messenger); rtp_terminate_session(call->crtps[video_index], av->messenger); free(call->frame_buf); LOGGER_WARNING("Jitter buffer creaton failed!"); return ErrorInternal; } if ( (call->cs = codec_init_session(codec_settings->audio_bitrate, codec_settings->audio_frame_duration, codec_settings->audio_sample_rate, codec_settings->audio_channels, codec_settings->audio_VAD_tolerance, codec_settings->video_width, codec_settings->video_height, codec_settings->video_bitrate) )) { call->call_active = 1; return ErrorNone; } 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); return ErrorInternal; }