Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ice memory reduction - enable ice stats flag #1947

Merged
merged 11 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,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 @@ -51,8 +51,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 @@ -114,21 +114,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 @@ -398,6 +398,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 @@ -533,6 +535,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;
disa6302 marked this conversation as resolved.
Show resolved Hide resolved
CHK_STATUS(initializePeerConnection(pSampleConfiguration, &pSampleStreamingSession->pPeerConnection));
CHK_STATUS(peerConnectionOnIceCandidate(pSampleStreamingSession->pPeerConnection, (UINT64) pSampleStreamingSession, onIceCandidateHandler));
CHK_STATUS(
Expand Down Expand Up @@ -1202,9 +1206,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 @@ -1536,7 +1539,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
Loading