return call->core;
}
+const LinphoneCallStats *linphone_call_get_audio_stats(const LinphoneCall *call) {
+ return &call->stats[LINPHONE_CALL_STATS_AUDIO];
+}
+
+const LinphoneCallStats *linphone_call_get_video_stats(const LinphoneCall *call) {
+ return &call->stats[LINPHONE_CALL_STATS_VIDEO];
+}
+
const char* linphone_call_get_authentication_token(LinphoneCall *call){
return call->auth_token;
}
if (port_offset==-1) return;
call->audio_port=linphone_core_get_audio_port(call->core)+port_offset;
call->video_port=linphone_core_get_video_port(call->core)+port_offset;
+ linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO);
+ linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO);
+}
+void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
+ stats->type = LINPHONE_CALL_STATS_AUDIO;
+ stats->received_rtcp = NULL;
+ stats->sent_rtcp = NULL;
}
static void discover_mtu(LinphoneCore *lc, const char *remote){
}
void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed){
+ LinphoneCore* lc = call->core;
int disconnect_timeout = linphone_core_get_nortp_timeout(call->core);
bool_t disconnected=FALSE;
OrtpEvent *ev;
while (NULL != (ev=ortp_ev_queue_get(call->videostream_app_evq))){
OrtpEventType evt=ortp_event_get_type(ev);
+ OrtpEventData *evd=ortp_event_get_data(ev);
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
- OrtpEventData *evd=ortp_event_get_data(ev);
linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
+ } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
+ call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->session);
+ if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL)
+ freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp);
+ call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet;
+ evd->packet = NULL;
+ if (lc->vtable.call_stats_updated)
+ lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
+ } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
+ memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->session), sizeof(jitter_stats_t));
+ if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL)
+ freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp);
+ call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet;
+ evd->packet = NULL;
+ if (lc->vtable.call_stats_updated)
+ lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
}
ortp_event_destroy(ev);
}
OrtpEvent *ev;
while (NULL != (ev=ortp_ev_queue_get(call->audiostream_app_evq))){
OrtpEventType evt=ortp_event_get_type(ev);
+ OrtpEventData *evd=ortp_event_get_data(ev);
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
- OrtpEventData *evd=ortp_event_get_data(ev);
linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
} else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
- OrtpEventData *evd=ortp_event_get_data(ev);
linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
+ } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
+ call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->session);
+ if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL)
+ freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp);
+ call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet;
+ evd->packet = NULL;
+ if (lc->vtable.call_stats_updated)
+ lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
+ } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
+ memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->session), sizeof(jitter_stats_t));
+ if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL)
+ freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp);
+ call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet;
+ evd->packet = NULL;
+ if (lc->vtable.call_stats_updated)
+ lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
}
ortp_event_destroy(ev);
}
**/
struct _LinphoneCall;
typedef struct _LinphoneCall LinphoneCall;
-
+
+
+#define LINPHONE_CALL_STATS_AUDIO 0
+#define LINPHONE_CALL_STATS_VIDEO 1
+
+typedef struct _LinphoneCallStats {
+ int type;
+ jitter_stats_t jitter_stats;
+ mblk_t* received_rtcp;
+ mblk_t* sent_rtcp;
+ float round_trip_delay;
+} LinphoneCallStats;
+
+const LinphoneCallStats *linphone_call_get_audio_stats(const LinphoneCall *call);
+const LinphoneCallStats *linphone_call_get_video_stats(const LinphoneCall *call);
+
+
/** Callback prototype */
typedef void (*LinphoneCallCbFunc)(struct _LinphoneCall *call,void * user_data);
typedef void (*BuddyInfoUpdated)(struct _LinphoneCore *lc, LinphoneFriend *lf);
/** Callback prototype for in progress transfers. The new_call_state is the state of the call resulting of the transfer, at the other party. */
typedef void (*LinphoneTransferStateChanged)(struct _LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state);
+/** Callback prototype */
+typedef void (*CallStatsUpdated)(struct _LinphoneCore *lc, LinphoneCall *call, LinphoneCallStats *stats);
/**
* This structure holds all callbacks that the application should implement.
DtmfReceived dtmf_received; /**< A dtmf has been received received */
ReferReceived refer_received; /**< An out of call refer was received */
CallEncryptionChangedCb call_encryption_changed; /**<Notifies on change in the encryption of call streams */
- LinphoneTransferStateChanged transfer_state_changed; /**<Notifies when a transfer is in progress */
+ LinphoneTransferStateChanged transfer_state_changed; /**<Notifies when a transfer is in progress */
BuddyInfoUpdated buddy_info_updated; /**< a LinphoneFriend's BuddyInfo has changed*/
NotifyReceivedCb notify_recv; /**< Other notifications*/
+ CallStatsUpdated call_stats_updated; /**<Notifies on change in the stats of call */
DisplayStatusCb display_status; /**< Callback that notifies various events with human readable text.*/
DisplayMessageCb display_message;/**< Callback to display a message to the user */
DisplayMessageCb display_warning;/** Callback to display a warning to the user */