diff --git a/README.md b/README.md index 52be2e5467..366201279e 100644 --- a/README.md +++ b/README.md @@ -513,9 +513,9 @@ In order to enable TWCC usage in the SDK, 2 things need to be set up: 1. Set the `disableSenderSideBandwidthEstimation` to FALSE. In our samples, the value is set using `disableTwcc` flag in `pSampleConfiguration` ```c -pSampleConfiguration->disableTwcc = TRUE; // to disable TWCC -pSampleConfiguration->disableTwcc = FALSE; // to enable TWCC -configuration.kvsRtcConfiguration.disableSenderSideBandwidthEstimation = pSampleConfiguration->disableTwcc; +pSampleConfiguration->enableTwcc = TRUE; // to enable TWCC +pSampleConfiguration->enableTwcc = FALSE; // to disable TWCC +configuration.kvsRtcConfiguration.disableSenderSideBandwidthEstimation = ~pSampleConfiguration->enableTwcc; ``` 2. Set the callback that will have the business logic to modify the bitrate based on packet loss information. The callback can be set using `peerConnectionOnSenderBandwidthEstimation()`. diff --git a/samples/Common.c b/samples/Common.c index 2b76d3d1dc..3768603c2e 100644 --- a/samples/Common.c +++ b/samples/Common.c @@ -414,7 +414,8 @@ STATUS initializePeerConnection(PSampleConfiguration pSampleConfiguration, PRtcP configuration.kvsRtcConfiguration.iceSetInterfaceFilterFunc = NULL; // disable TWCC - configuration.kvsRtcConfiguration.disableSenderSideBandwidthEstimation = pSampleConfiguration->disableTwcc; + configuration.kvsRtcConfiguration.disableSenderSideBandwidthEstimation = !(pSampleConfiguration->enableTwcc); + DLOGI("Disable: %s", configuration.kvsRtcConfiguration.disableSenderSideBandwidthEstimation ? "Disabled" : "Enabled"); // Set the ICE mode explicitly configuration.iceTransportPolicy = ICE_TRANSPORT_POLICY_ALL; @@ -557,9 +558,9 @@ STATUS createSampleStreamingSession(PSampleConfiguration pSampleConfiguration, P 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; - pSampleConfiguration->disableTwcc = FALSE; + pSampleConfiguration->enableTwcc = TRUE; - if (!pSampleConfiguration->disableTwcc) { + if (pSampleConfiguration->enableTwcc) { pSampleStreamingSession->twccMetadata.updateLock = MUTEX_CREATE(TRUE); } @@ -609,7 +610,7 @@ STATUS createSampleStreamingSession(PSampleConfiguration pSampleConfiguration, P CHK_STATUS(transceiverOnBandwidthEstimation(pSampleStreamingSession->pAudioRtcRtpTransceiver, (UINT64) pSampleStreamingSession, sampleBandwidthEstimationHandler)); // twcc bandwidth estimation - if (!pSampleConfiguration->disableTwcc) { + if (pSampleConfiguration->enableTwcc) { CHK_STATUS(peerConnectionOnSenderBandwidthEstimation(pSampleStreamingSession->pPeerConnection, (UINT64) pSampleStreamingSession, sampleSenderBandwidthEstimationHandler)); } @@ -663,7 +664,7 @@ STATUS freeSampleStreamingSession(PSampleStreamingSession* ppSampleStreamingSess } MUTEX_UNLOCK(pSampleConfiguration->sampleConfigurationObjLock); - if (!pSampleConfiguration->disableTwcc) { + if (pSampleConfiguration->enableTwcc) { if (IS_VALID_MUTEX_VALUE(pSampleStreamingSession->twccMetadata.updateLock)) { MUTEX_FREE(pSampleStreamingSession->twccMetadata.updateLock); } @@ -743,7 +744,7 @@ VOID sampleSenderBandwidthEstimationHandler(UINT64 customData, UINT32 txBytes, U currentTimeMs = GETTIME(); timeDiff = currentTimeMs - pSampleStreamingSession->twccMetadata.lastAdjustmentTimeMs; - if (timeDiff < ADJUSTMENT_INTERVAL_SECONDS) { + if (timeDiff < TWCC_BITRATE_ADJUSTMENT_INTERVAL_SECONDS) { // Too soon for another adjustment return; } @@ -755,15 +756,11 @@ VOID sampleSenderBandwidthEstimationHandler(UINT64 customData, UINT32 txBytes, U if (pSampleStreamingSession->twccMetadata.averagePacketLoss <= 5) { // increase encoder bitrate by 5 percent with a cap at MAX_BITRATE videoBitrate = (UINT64) MIN(videoBitrate * 1.05, MAX_VIDEO_BITRATE_KBPS); - } else { - // decrease encoder bitrate by average packet loss percent, with a cap at MIN_BITRATE - videoBitrate = (UINT64) MAX(videoBitrate * (1.0 - pSampleStreamingSession->twccMetadata.averagePacketLoss / 100.0), MIN_VIDEO_BITRATE_KBPS); - } - - if (pSampleStreamingSession->twccMetadata.averagePacketLoss <= 5) { // increase encoder bitrate by 5 percent with a cap at MAX_BITRATE audioBitrate = (UINT64) MIN(audioBitrate * 1.05, MAX_AUDIO_BITRATE_BPS); } else { + // decrease encoder bitrate by average packet loss percent, with a cap at MIN_BITRATE + videoBitrate = (UINT64) MAX(videoBitrate * (1.0 - pSampleStreamingSession->twccMetadata.averagePacketLoss / 100.0), MIN_VIDEO_BITRATE_KBPS); // decrease encoder bitrate by average packet loss percent, with a cap at MIN_BITRATE audioBitrate = (UINT64) MAX(audioBitrate * (1.0 - pSampleStreamingSession->twccMetadata.averagePacketLoss / 100.0), MIN_AUDIO_BITRATE_BPS); } @@ -776,7 +773,7 @@ VOID sampleSenderBandwidthEstimationHandler(UINT64 customData, UINT32 txBytes, U pSampleStreamingSession->twccMetadata.lastAdjustmentTimeMs = currentTimeMs; DLOGI("Adjustment made: average packet loss = %.2f%%, timediff: %llu ms", pSampleStreamingSession->twccMetadata.averagePacketLoss, - ADJUSTMENT_INTERVAL_SECONDS, timeDiff); + TWCC_BITRATE_ADJUSTMENT_INTERVAL_SECONDS, timeDiff); DLOGI("Suggested video bitrate %u kbps, suggested audio bitrate: %u bps, sent: %u bytes %u packets received: %u bytes %u packets in %lu msec", videoBitrate, audioBitrate, txBytes, txPacketsCnt, rxBytes, rxPacketsCnt, duration / 10000ULL); } diff --git a/samples/Samples.h b/samples/Samples.h index cf8f0cdd3e..7901a58cf7 100644 --- a/samples/Samples.h +++ b/samples/Samples.h @@ -83,11 +83,11 @@ extern "C" { #define MAX_SIGNALING_CLIENT_METRICS_MESSAGE_SIZE 736 // strlen(SIGNALING_CLIENT_METRICS_JSON_TEMPLATE) + 20 * 10 #define MAX_ICE_AGENT_METRICS_MESSAGE_SIZE 113 // strlen(ICE_AGENT_METRICS_JSON_TEMPLATE) + 20 * 2 -#define ADJUSTMENT_INTERVAL_SECONDS 1 * HUNDREDS_OF_NANOS_IN_A_SECOND -#define MIN_VIDEO_BITRATE_KBPS 512 // Unit kilobits/sec. Value could change based on codec. -#define MAX_VIDEO_BITRATE_KBPS 2048000 // Unit kilobits/sec. Value could change based on codec. -#define MIN_AUDIO_BITRATE_BPS 4000 // Unit bits/sec. Value could change based on codec. -#define MAX_AUDIO_BITRATE_BPS 650000 // Unit bits/sec. Value could change based on codec. +#define TWCC_BITRATE_ADJUSTMENT_INTERVAL_SECONDS 1 * HUNDREDS_OF_NANOS_IN_A_SECOND +#define MIN_VIDEO_BITRATE_KBPS 512 // Unit kilobits/sec. Value could change based on codec. +#define MAX_VIDEO_BITRATE_KBPS 2048000 // Unit kilobits/sec. Value could change based on codec. +#define MIN_AUDIO_BITRATE_BPS 4000 // Unit bits/sec. Value could change based on codec. +#define MAX_AUDIO_BITRATE_BPS 650000 // Unit bits/sec. Value could change based on codec. typedef enum { SAMPLE_STREAMING_VIDEO_ONLY, @@ -166,7 +166,7 @@ typedef struct { PCHAR rtspUri; UINT32 logLevel; BOOL enableIceStats; - BOOL disableTwcc; + BOOL enableTwcc; } SampleConfiguration, *PSampleConfiguration; typedef struct { diff --git a/samples/kvsWebRTCClientMasterGstSample.c b/samples/kvsWebRTCClientMasterGstSample.c index 2f6a0a75ce..d23d89ad7a 100644 --- a/samples/kvsWebRTCClientMasterGstSample.c +++ b/samples/kvsWebRTCClientMasterGstSample.c @@ -66,7 +66,7 @@ GstFlowReturn on_new_sample(GstElement* sink, gpointer data, UINT64 trackid) frame.index = (UINT32) ATOMIC_INCREMENT(&pSampleStreamingSession->frameIndex); if (trackid == DEFAULT_AUDIO_TRACK_ID) { - if (!pSampleStreamingSession->pSampleConfiguration->disableTwcc && senderPipeline != NULL) { + if (pSampleStreamingSession->pSampleConfiguration->enableTwcc && senderPipeline != NULL) { GstElement* encoder = gst_bin_get_by_name(GST_BIN(senderPipeline), "sampleAudioEncoder"); if (encoder != NULL) { g_object_get(G_OBJECT(encoder), "bitrate", &bitrate, NULL); @@ -86,7 +86,7 @@ GstFlowReturn on_new_sample(GstElement* sink, gpointer data, UINT64 trackid) pSampleStreamingSession->audioTimestamp += SAMPLE_AUDIO_FRAME_DURATION; // assume audio frame size is 20ms, which is default in opusenc } else { - if (!pSampleStreamingSession->pSampleConfiguration->disableTwcc && senderPipeline != NULL) { + if (pSampleStreamingSession->pSampleConfiguration->enableTwcc && senderPipeline != NULL) { GstElement* encoder = gst_bin_get_by_name(GST_BIN(senderPipeline), "sampleVideoEncoder"); if (encoder != NULL) { g_object_get(G_OBJECT(encoder), "bitrate", &bitrate, NULL);