Skip to content

Commit

Permalink
Ice memory reduction - enable ice stats flag (#1947)
Browse files Browse the repository at this point in the history
* Change params size

* Use dyanmic allocation and flag for ice stats

* Debug 1

* Revert "Debug 1"

This reverts commit ad7d02f.

* Revert "Use dyanmic allocation and flag for ice stats"

This reverts commit bf9a2ee.

* Working version

* enable flag in samples

* Add unit test

* Fix bug

* README for the flag

* Update readme
  • Loading branch information
disa6302 authored Mar 18, 2024
1 parent 76913ff commit 7be31c1
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 194 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,18 @@ Let us look into when each of these could be changed:
3. `iceConnectionCheckTimeout`: It is useful to increase this timeout in unstable/slow network where the packet exchange takes time and hence the binding request/response. Essentially, increasing it will allow atleast one candidate pair to be tried for nomination by the other peer.
4. `iceConnectionCheckPollingInterval`: This value is set to a default of 50 ms per [spec](https://datatracker.ietf.org/doc/html/rfc8445#section-14.2). Changing this would change the frequency of connectivity checks and essentially, the ICE state machine transitions. Decreasing the value could help in faster connection establishment in a reliable high performant network setting with good system resources. Increasing the value could help in reducing the network load, however, the connection establishment could slow down. Unless there is a strong reasoning, it is **NOT** recommended to deviate from spec/default.
### Enable ICE agent stats
The SDK calculates 4 different stats:
1. ICE server stats - stats for ICE servers the SDK is using
2. [Local candidate stats](https://www.w3.org/TR/webrtc-stats/#dom-rtcstatstype-local-candidate) - stats for the selected local candidate
3. [Remote candidate stats](https://www.w3.org/TR/webrtc-stats/#dom-rtcstatstype-remote-candidate) - stats for the selected remote candidate
4. [Candidate pair stats](https://www.w3.org/TR/webrtc-stats/#dom-rtcstatstype-candidate-pair) - stats for the selected candidate pair
For more information on these stats, refer to [AWS Docs](https://docs.aws.amazon.com/kinesisvideostreams-webrtc-dg/latest/devguide/kvswebrtc-reference.html)
The SDK disables generating these stats by default. In order to be enable the SDK to calculate these stats, the application needs to set the following field:
`configuration.kvsRtcConfiguration.enableIceStats = TRUE`.
### Controlling RTP rolling buffer capacity
Expand Down
39 changes: 21 additions & 18 deletions samples/Common.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ VOID onConnectionStateChange(UINT64 customData, RTC_PEER_CONNECTION_STATE newSta
CHK_STATUS(peerConnectionGetMetrics(pSampleStreamingSession->pPeerConnection, &pSampleStreamingSession->peerConnectionMetrics));
CHK_STATUS(iceAgentGetMetrics(pSampleStreamingSession->pPeerConnection, &pSampleStreamingSession->iceMetrics));

if (STATUS_FAILED(retStatus = logSelectedIceCandidatesInformation(pSampleStreamingSession))) {
DLOGW("Failed to get information about selected Ice candidates: 0x%08x", retStatus);
if (pSampleConfiguration->enableIceStats) {
CHK_LOG_ERR(logSelectedIceCandidatesInformation(pSampleStreamingSession));
}
break;
case RTC_PEER_CONNECTION_STATE_FAILED:
Expand Down Expand Up @@ -117,21 +117,21 @@ STATUS logSelectedIceCandidatesInformation(PSampleStreamingSession pSampleStream
CHK(pSampleStreamingSession != NULL, STATUS_NULL_ARG);
rtcMetrics.requestedTypeOfStats = RTC_STATS_TYPE_LOCAL_CANDIDATE;
CHK_STATUS(rtcPeerConnectionGetMetrics(pSampleStreamingSession->pPeerConnection, NULL, &rtcMetrics));
DLOGD("Local Candidate IP Address: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.address);
DLOGD("Local Candidate type: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.candidateType);
DLOGD("Local Candidate port: %d", rtcMetrics.rtcStatsObject.localIceCandidateStats.port);
DLOGD("Local Candidate priority: %d", rtcMetrics.rtcStatsObject.localIceCandidateStats.priority);
DLOGD("Local Candidate transport protocol: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.protocol);
DLOGD("Local Candidate relay protocol: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.relayProtocol);
DLOGD("Local Candidate Ice server source: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.url);
DLOGI("Local Candidate IP Address: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.address);
DLOGI("Local Candidate type: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.candidateType);
DLOGI("Local Candidate port: %d", rtcMetrics.rtcStatsObject.localIceCandidateStats.port);
DLOGI("Local Candidate priority: %d", rtcMetrics.rtcStatsObject.localIceCandidateStats.priority);
DLOGI("Local Candidate transport protocol: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.protocol);
DLOGI("Local Candidate relay protocol: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.relayProtocol);
DLOGI("Local Candidate Ice server source: %s", rtcMetrics.rtcStatsObject.localIceCandidateStats.url);

rtcMetrics.requestedTypeOfStats = RTC_STATS_TYPE_REMOTE_CANDIDATE;
CHK_STATUS(rtcPeerConnectionGetMetrics(pSampleStreamingSession->pPeerConnection, NULL, &rtcMetrics));
DLOGD("Remote Candidate IP Address: %s", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.address);
DLOGD("Remote Candidate type: %s", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.candidateType);
DLOGD("Remote Candidate port: %d", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.port);
DLOGD("Remote Candidate priority: %d", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.priority);
DLOGD("Remote Candidate transport protocol: %s", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.protocol);
DLOGI("Remote Candidate IP Address: %s", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.address);
DLOGI("Remote Candidate type: %s", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.candidateType);
DLOGI("Remote Candidate port: %d", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.port);
DLOGI("Remote Candidate priority: %d", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.priority);
DLOGI("Remote Candidate transport protocol: %s", rtcMetrics.rtcStatsObject.remoteIceCandidateStats.protocol);
CleanUp:
LEAVES();
return retStatus;
Expand Down Expand Up @@ -414,6 +414,8 @@ STATUS initializePeerConnection(PSampleConfiguration pSampleConfiguration, PRtcP
// Set the ICE mode explicitly
configuration.iceTransportPolicy = ICE_TRANSPORT_POLICY_ALL;

configuration.kvsRtcConfiguration.enableIceStats = pSampleConfiguration->enableIceStats;

// Set the STUN server
PCHAR pKinesisVideoStunUrlPostFix = KINESIS_VIDEO_STUN_URL_POSTFIX;
// If region is in CN, add CN region uri postfix
Expand Down Expand Up @@ -549,6 +551,8 @@ STATUS createSampleStreamingSession(PSampleConfiguration pSampleConfiguration, P
ATOMIC_STORE_BOOL(&pSampleStreamingSession->candidateGatheringDone, FALSE);

pSampleStreamingSession->peerConnectionMetrics.peerConnectionStats.peerConnectionStartTime = GETTIME() / HUNDREDS_OF_NANOS_IN_A_MILLISECOND;
// Flag to enable SDK to calculate selected ice server, local, remote and candidate pair stats.
pSampleConfiguration->enableIceStats = FALSE;
CHK_STATUS(initializePeerConnection(pSampleConfiguration, &pSampleStreamingSession->pPeerConnection));
CHK_STATUS(peerConnectionOnIceCandidate(pSampleStreamingSession->pPeerConnection, (UINT64) pSampleStreamingSession, onIceCandidateHandler));
CHK_STATUS(
Expand Down Expand Up @@ -1218,9 +1222,8 @@ STATUS freeSampleConfiguration(PSampleConfiguration* ppSampleConfiguration)
}

for (i = 0; i < pSampleConfiguration->streamingSessionCount; ++i) {
retStatus = gatherIceServerStats(pSampleConfiguration->sampleStreamingSessionList[i]);
if (STATUS_FAILED(retStatus)) {
DLOGW("Failed to ICE Server Stats for streaming session %d: %08x", i, retStatus);
if (pSampleConfiguration->enableIceStats) {
CHK_LOG_ERR(gatherIceServerStats(pSampleConfiguration->sampleStreamingSessionList[i]));
}
freeSampleStreamingSession(&pSampleConfiguration->sampleStreamingSessionList[i]);
}
Expand Down Expand Up @@ -1552,7 +1555,7 @@ STATUS signalingMessageReceived(UINT64 customData, PReceivedSignalingMessage pRe
MUTEX_UNLOCK(pSampleConfiguration->sampleConfigurationObjLock);
locked = FALSE;

if (startStats &&
if (pSampleConfiguration->enableIceStats && startStats &&
STATUS_FAILED(retStatus = timerQueueAddTimer(pSampleConfiguration->timerQueueHandle, SAMPLE_STATS_DURATION, SAMPLE_STATS_DURATION,
getIceCandidatePairStatsCallback, (UINT64) pSampleConfiguration,
&pSampleConfiguration->iceCandidatePairStatsTimerId))) {
Expand Down
1 change: 1 addition & 0 deletions samples/Samples.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ typedef struct {

PCHAR rtspUri;
UINT32 logLevel;
BOOL enableIceStats;
} SampleConfiguration, *PSampleConfiguration;

typedef struct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,11 +477,6 @@ extern "C" {
*/
#define MAX_SIGNALING_ENDPOINT_URI_LEN 512

/**
* Maximum allowed ICE URI length
*/
#define MAX_ICE_CONFIG_URI_LEN 256

/**
* Maximum allowed correlation ID length
*/
Expand Down Expand Up @@ -1220,6 +1215,7 @@ typedef struct {
BOOL disableSenderSideBandwidthEstimation; //!< Disable TWCC feedback based sender bandwidth estimation, enabled by default.
//!< You want to set this to TRUE if you are on a very stable connection and want to save 1.2MB of
//!< memory
BOOL enableIceStats; //!< Enable ICE stats to be calculated
} KvsRtcConfiguration, *PKvsRtcConfiguration;

/**
Expand Down
43 changes: 26 additions & 17 deletions src/include/com/amazonaws/kinesis/video/webrtcclient/Stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ extern "C" {
*/
#define MAX_CANDIDATE_ID_LENGTH 9U

/**
* Maximum allowed ICE URI length
*/
#define MAX_ICE_CONFIG_URI_LEN 256

/**
* Maximum allowed relay protocol length
*/
Expand Down Expand Up @@ -63,6 +68,11 @@ extern "C" {
* Maximum allowed generic length used in DOMString
*/
#define MAX_STATS_STRING_LENGTH 255U

/**
* Maximum length of candidate type (host, srflx, relay, prflx, unknown)
*/
#define MAX_CANDIDATE_TYPE_LENGTH 10U
/*!@} */

/**
Expand Down Expand Up @@ -233,14 +243,14 @@ typedef struct {
* Reference: https://www.w3.org/TR/webrtc-stats/#ice-server-dict*
*/
typedef struct {
DOMString url; //!< STUN/TURN server URL
DOMString protocol; //!< Valid values: UDP, TCP
UINT32 iceServerIndex; //!< Ice server index to get stats from. Not available in spec! Needs to be
//!< populated by the application to get specific server stats
INT32 port; //!< Port number used by client
UINT64 totalRequestsSent; //!< Total amount of requests that have been sent to the server
UINT64 totalResponsesReceived; //!< Total number of responses received from the server
UINT64 totalRoundTripTime; //!< Sum of RTTs of all the requests for which response has been received
CHAR url[MAX_ICE_CONFIG_URI_LEN + 1]; //!< STUN/TURN server URL
CHAR protocol[MAX_PROTOCOL_LENGTH + 1]; //!< Valid values: UDP, TCP
UINT32 iceServerIndex; //!< Ice server index to get stats from. Not available in spec! Needs to be
//!< populated by the application to get specific server stats
INT32 port; //!< Port number used by client
UINT64 totalRequestsSent; //!< Total amount of requests that have been sent to the server
UINT64 totalResponsesReceived; //!< Total number of responses received from the server
UINT64 totalRoundTripTime; //!< Sum of RTTs of all the requests for which response has been received
} RtcIceServerStats, *PRtcIceServerStats;

/**
Expand All @@ -267,15 +277,14 @@ typedef struct {
*/

typedef struct {
DOMString url; //!< For local candidates this is the URL of the ICE server from which the candidate was obtained
DOMString transportId; //!< Not used currently. ID of object that was inspected for RTCTransportStats
CHAR address[IP_ADDR_STR_LENGTH + 1]; //!< IPv4 or IPv6 address of the candidate
DOMString protocol; //!< Valid values: UDP, TCP
DOMString relayProtocol; //!< Protocol used by endpoint to communicate with TURN server. (Only for local candidate)
//!< Valid values: UDP, TCP, TLS
INT32 priority; //!< Computed using the formula in https://tools.ietf.org/html/rfc5245#section-15.1
INT32 port; //!< Port number of the candidate
DOMString candidateType; //!< Type of local/remote ICE candidate
DOMString url; //!< For local candidates this is the URL of the ICE server from which the candidate was obtained
CHAR address[IP_ADDR_STR_LENGTH + 1]; //!< IPv4 or IPv6 address of the candidate
CHAR protocol[MAX_PROTOCOL_LENGTH + 1]; //!< Valid values: UDP, TCP
CHAR relayProtocol[MAX_PROTOCOL_LENGTH + 1]; //!< Protocol used by endpoint to communicate with TURN server. (Only for local candidate)
//!< Valid values: UDP, TCP, TLS
INT32 priority; //!< Computed using the formula in https://tools.ietf.org/html/rfc5245#section-15.1
INT32 port; //!< Port number of the candidate
CHAR candidateType[MAX_CANDIDATE_TYPE_LENGTH + 1]; //!< Type of local/remote ICE candidate
} RtcIceCandidateStats, *PRtcIceCandidateStats;

/**
Expand Down
Loading

0 comments on commit 7be31c1

Please sign in to comment.