Commit a244da20 authored by Mickaël Turnel's avatar Mickaël Turnel

Add a TMMBR callback

parent 5c266997
......@@ -47,6 +47,7 @@ void linphone_call_notify_transfer_state_changed(LinphoneCall *call, LinphoneCal
void linphone_call_notify_stats_updated(LinphoneCall *call, const LinphoneCallStats *stats);
void linphone_call_notify_info_message_received(LinphoneCall *call, const LinphoneInfoMessage *msg);
void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *msg, bool_t is_received);
void linphone_call_notify_tmmbr_received(LinphoneCall *call, int stream_index, int tmmbr);
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg);
LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, LinphonePrivate::SalCallOp *op);
......
......@@ -159,6 +159,20 @@ LINPHONE_PUBLIC LinphoneCallCbsAckProcessingCb linphone_call_cbs_get_ack_process
*/
LINPHONE_PUBLIC void linphone_call_cbs_set_ack_processing (LinphoneCallCbs *cbs, LinphoneCallCbsAckProcessingCb cb);
/**
* Get the TMMBR received callback.
* @param[in] cbs LinphoneCallCbs object.
* @return The current TMMBR received callback.
*/
LINPHONE_PUBLIC LinphoneCallCbsTmmbrReceivedCb linphone_call_cbs_get_tmmbr_received(LinphoneCallCbs *cbs);
/**
* Set the TMMBR received callback.
* @param[in] cbs LinphoneCallCbs object.
* @param[in] cb The TMMBR received callback to be used.
*/
LINPHONE_PUBLIC void linphone_call_cbs_set_tmmbr_received(LinphoneCallCbs *cbs, LinphoneCallCbsTmmbrReceivedCb cb);
/**
* @}
*/
......
......@@ -87,6 +87,14 @@ typedef void (*LinphoneCallCbsTransferStateChangedCb)(LinphoneCall *call, Linpho
*/
typedef void (*LinphoneCallCbsAckProcessingCb)(LinphoneCall *call, LinphoneHeaders *ack, bool_t is_received);
/**
* Callback for notifying a received TMMBR.
* @param call LinphoneCall for which the TMMBR has changed
* @param stream_index the index of the current stream
* @param tmmbr the value of the received TMMBR
*/
typedef void (*LinphoneCallCbsTmmbrReceivedCb)(LinphoneCall *call, int stream_index, int tmmbr);
/**
* @}
**/
......
......@@ -33,6 +33,7 @@ struct _LinphoneCallCbs {
LinphoneCallCbsStatsUpdatedCb statsUpdatedCb;
LinphoneCallCbsTransferStateChangedCb transferStateChangedCb;
LinphoneCallCbsAckProcessingCb ackProcessing;
LinphoneCallCbsTmmbrReceivedCb tmmbrReceivedCb;
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCallCbs);
......@@ -124,3 +125,11 @@ LinphoneCallCbsAckProcessingCb linphone_call_cbs_get_ack_processing (LinphoneCal
void linphone_call_cbs_set_ack_processing (LinphoneCallCbs *cbs, LinphoneCallCbsAckProcessingCb cb){
cbs->ackProcessing = cb;
}
LinphoneCallCbsTmmbrReceivedCb linphone_call_cbs_get_tmmbr_received (LinphoneCallCbs *cbs) {
return cbs->tmmbrReceivedCb;
}
void linphone_call_cbs_set_tmmbr_received (LinphoneCallCbs *cbs, LinphoneCallCbsTmmbrReceivedCb cb) {
cbs->tmmbrReceivedCb = cb;
}
......@@ -206,6 +206,10 @@ void linphone_call_notify_ack_processing (LinphoneCall *call, LinphoneHeaders *m
NOTIFY_IF_EXIST(AckProcessing, ack_processing, call, msg, is_received)
}
void linphone_call_notify_tmmbr_received (LinphoneCall *call, int stream_index, int tmmbr) {
NOTIFY_IF_EXIST(TmmbrReceived, tmmbr_received, call, stream_index, tmmbr)
}
// =============================================================================
// Public functions.
......
......@@ -110,6 +110,7 @@ private:
bool areSoundResourcesAvailable (const std::shared_ptr<CallSession> &session) override;
bool isPlayingRingbackTone (const std::shared_ptr<CallSession> &session) override;
void onRealTimeTextCharacterReceived (const std::shared_ptr<CallSession> &session, RealtimeTextReceivedCharacter *character) override;
void onTmmbrReceived(const std::shared_ptr<CallSession> &session, int streamIndex, int tmmbr) override;
mutable LinphonePlayer *player = nullptr;
......
......@@ -491,6 +491,11 @@ void CallPrivate::onRealTimeTextCharacterReceived (const shared_ptr<CallSession>
getChatRoom()->getPrivate()->realtimeTextReceived(data->character, q->getSharedFromThis());
}
void CallPrivate::onTmmbrReceived (const shared_ptr<CallSession> &session, int streamIndex, int tmmbr) {
L_Q();
linphone_call_notify_tmmbr_received(L_GET_C_BACK_PTR(q), streamIndex, tmmbr);
}
// =============================================================================
Call::Call (CallPrivate &p, shared_ptr<Core> core) : Object(p), CoreAccessor(core) {
......
......@@ -54,6 +54,7 @@ public:
virtual void onIncomingCallSessionTimeoutCheck (const std::shared_ptr<CallSession> &session, int elapsed, bool oneSecondElapsed) {}
virtual void onInfoReceived (const std::shared_ptr<CallSession> &session, const LinphoneInfoMessage *im) {}
virtual void onNoMediaTimeoutCheck (const std::shared_ptr<CallSession> &session, bool oneSecondElapsed) {}
virtual void onTmmbrReceived (const std::shared_ptr<CallSession> &session, int streamIndex, int tmmbr) {}
virtual void onEncryptionChanged (const std::shared_ptr<CallSession> &session, bool activated, const std::string &authToken) {}
......
......@@ -2238,6 +2238,7 @@ void MediaSessionPrivate::handleIceEvents (OrtpEvent *ev) {
}
void MediaSessionPrivate::handleStreamEvents (int streamIndex) {
L_Q();
MediaStream *ms = (streamIndex == mainAudioStreamIndex) ? &audioStream->ms :
(streamIndex == mainVideoStreamIndex ? &videoStream->ms : &textStream->ms);
if (ms) {
......@@ -2272,14 +2273,28 @@ void MediaSessionPrivate::handleStreamEvents (int streamIndex) {
stats = videoStats;
else
stats = textStats;
OrtpEventType evt = ortp_event_get_type(ev);
OrtpEventData *evd = ortp_event_get_data(ev);
/*This MUST be done before any call to "linphone_call_stats_fill" since it has ownership over evd->packet*/
if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
do {
if (evd->packet && rtcp_is_RTPFB(evd->packet)) {
if (rtcp_RTPFB_get_type(evd->packet) == RTCP_RTPFB_TMMBR) {
listener->onTmmbrReceived(q->getSharedFromThis(), streamIndex, (int)rtcp_RTPFB_tmmbr_get_max_bitrate(evd->packet));
}
}
} while (rtcp_next_packet(evd->packet));
rtcp_rewind(evd->packet);
}
/* And yes the MediaStream must be taken at each iteration, because it may have changed due to the handling of events
* in this loop*/
ms = getMediaStream(streamIndex);
if (ms)
linphone_call_stats_fill(stats, ms, ev);
notifyStatsUpdated(streamIndex);
OrtpEventType evt = ortp_event_get_type(ev);
OrtpEventData *evd = ortp_event_get_data(ev);
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED) {
if (streamIndex == mainAudioStreamIndex)
audioStreamEncryptionChanged(!!evd->info.zrtp_stream_encrypted);
......
......@@ -2008,6 +2008,70 @@ static void video_call_with_thin_congestion(void){
linphone_core_manager_destroy(pauline);
}
static void on_tmmbr_received(LinphoneCall *call, int stream_index, int tmmbr) {
if (stream_index == _linphone_call_get_main_video_stream_index(call)) {
stats* stat = get_stats(linphone_call_get_core(call));
stat->tmmbr_received_from_cb = tmmbr;
}
}
static void call_created(LinphoneCore *lc, LinphoneCall *call) {
LinphoneCallCbs *cbs = linphone_factory_create_call_cbs(linphone_factory_get());
linphone_call_cbs_set_tmmbr_received(cbs, on_tmmbr_received);
linphone_call_add_callbacks(call, cbs);
linphone_call_cbs_unref(cbs);
}
/*
* This test simulates a higher bandwith available from marie than expected.
* The stream from pauline to marie is not under test.
* It checks that after a few seconds marie received a TMMBR with the approximate value corresponding to the new bandwidth.
*
**/
static void video_call_with_high_bandwidth_available(void) {
LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc");
LinphoneVideoPolicy pol = {0};
OrtpNetworkSimulatorParams simparams = { 0 };
LinphoneCoreCbs *core_cbs = linphone_factory_create_core_cbs(linphone_factory_get());
linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)");
linphone_core_enable_video_capture(marie->lc, TRUE);
linphone_core_enable_video_display(marie->lc, TRUE);
linphone_core_enable_video_capture(pauline->lc, TRUE);
linphone_core_enable_video_display(pauline->lc, TRUE);
pol.automatically_accept = TRUE;
pol.automatically_initiate = TRUE;
linphone_core_set_video_policy(marie->lc, &pol);
linphone_core_set_video_policy(pauline->lc, &pol);
linphone_core_set_preferred_video_size_by_name(marie->lc, "vga");
simparams.mode = OrtpNetworkSimulatorOutbound;
simparams.enabled = TRUE;
simparams.max_bandwidth = 1000000;
simparams.max_buffer_size = (int)simparams.max_bandwidth;
simparams.latency = 60;
linphone_core_set_network_simulator_params(marie->lc, &simparams);
linphone_core_cbs_set_call_created(core_cbs, call_created);
linphone_core_add_callbacks(marie->lc, core_cbs);
if (BC_ASSERT_TRUE(call(marie, pauline))){
/*wait a little in order to have traffic*/
BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, NULL, 5, 50000));
BC_ASSERT_GREATER((float)marie->stat.last_tmmbr_value_received, 870000.f, float, "%f");
BC_ASSERT_LOWER((float)marie->stat.last_tmmbr_value_received, 1150000.f, float, "%f");
end_call(marie, pauline);
}
linphone_core_cbs_unref(core_cbs);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
test_t call_video_tests[] = {
#ifdef VIDEO_ENABLED
TEST_NO_TAG("Call paused resumed with video", call_paused_resumed_with_video),
......@@ -2073,10 +2137,11 @@ test_t call_video_tests[] = {
TEST_NO_TAG("Classic video entry phone setup", classic_video_entry_phone_setup),
TEST_NO_TAG("Incoming REINVITE with invalid SDP in ACK", incoming_reinvite_with_invalid_ack_sdp),
TEST_NO_TAG("Outgoing REINVITE with invalid SDP in ACK", outgoing_reinvite_with_invalid_ack_sdp),
#endif
TEST_NO_TAG("Video call with no audio and no video codec", video_call_with_no_audio_and_no_video_codec),
TEST_NO_TAG("Call with early media and no SDP in 200 Ok with video", call_with_early_media_and_no_sdp_in_200_with_video),
TEST_NO_TAG("Video call with thin congestion", video_call_with_thin_congestion)
TEST_NO_TAG("Video call with thin congestion", video_call_with_thin_congestion),
TEST_NO_TAG("Video call with high bandwidth available", video_call_with_high_bandwidth_available)
#endif
};
test_suite_t call_video_test_suite = {"Video Call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,
......
......@@ -283,6 +283,7 @@ typedef struct _stats {
int number_of_rtcp_generic_nack;
int number_of_tmmbr_received;
int last_tmmbr_value_received;
int tmmbr_received_from_cb;
int number_of_participants_added;
int number_of_participant_admin_statuses_changed;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment