Skip to content
This repository was archived by the owner on Mar 22, 2022. It is now read-only.

Commit 28dfdf1

Browse files
fiban-havokjehumb-havok
authored andcommitted
Expose PeerConnectionInterface::SetBitrate (#109)
Expose webrtc::PeerConnectionInterface::SetBitrate() to allow the user to set the minimum and maximum bitrates used for the RTP tracks, as well as the starting value. This enables in particular changing the default video value of 300 kpbs to something higher in local scenarios where the bandwidth is expected to be high, to enable higher quality video right from the start of the video track recording.
1 parent 766d27e commit 28dfdf1

6 files changed

Lines changed: 75 additions & 9 deletions

File tree

examples/TestAppUwp/MainPage.xaml.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ private Task RunOnWorkerThread(Action handler)
705705
/// <param name="width">The width of the video in pixels.</param>
706706
/// <param name="height">The height of the video in pixels.</param>
707707
/// <returns>The newly created video source.</returns>
708-
private MediaStreamSource CreateVideoStreamSource(uint width, uint height)
708+
private MediaStreamSource CreateVideoStreamSource(uint width, uint height, uint framerate)
709709
{
710710
if (width == 0)
711711
{
@@ -720,7 +720,7 @@ private MediaStreamSource CreateVideoStreamSource(uint width, uint height)
720720
// https://docs.microsoft.com/en-us/windows/desktop/medfound/video-subtype-guids
721721
var videoProperties = VideoEncodingProperties.CreateUncompressed(MediaEncodingSubtypes.Iyuv, width, height);
722722
var videoStreamDesc = new VideoStreamDescriptor(videoProperties);
723-
videoStreamDesc.EncodingProperties.FrameRate.Numerator = 30;
723+
videoStreamDesc.EncodingProperties.FrameRate.Numerator = framerate;
724724
videoStreamDesc.EncodingProperties.FrameRate.Denominator = 1;
725725
videoStreamDesc.EncodingProperties.Bitrate = (30 * width * height * 8 * 8 / 12); // 30-fps 8bits/byte NV12=12bpp
726726
var videoStreamSource = new MediaStreamSource(videoStreamDesc);
@@ -975,8 +975,10 @@ private void Peer_RemoteI420FrameReady(I420AVideoFrame frame)
975975
_isRemoteVideoPlaying = true;
976976
uint width = frame.width;
977977
uint height = frame.height;
978+
// We don't know the remote video framerate yet, so use a default.
979+
uint framerate = 30;
978980
RunOnMainThread(() => {
979-
remoteVideoSource = CreateVideoStreamSource(width, height);
981+
remoteVideoSource = CreateVideoStreamSource(width, height, framerate);
980982
remoteVideoPlayer.Source = MediaSource.CreateFromMediaStreamSource(remoteVideoSource);
981983
remoteVideoPlayer.Play();
982984
});
@@ -1129,7 +1131,7 @@ private async void StartLocalMediaClicked(object sender, RoutedEventArgs e)
11291131
localMediaSource?.Reset();
11301132
localVideo.SetMediaPlayer(null);
11311133
localVideoSource = null;
1132-
localVideoSource = CreateVideoStreamSource(width, height);
1134+
localVideoSource = CreateVideoStreamSource(width, height, (uint)framerate);
11331135
localMediaSource = MediaSource.CreateFromMediaStreamSource(localVideoSource);
11341136
localVideoPlayer.Source = localMediaSource;
11351137
localVideo.SetMediaPlayer(localVideoPlayer);
@@ -1143,6 +1145,10 @@ private async void StartLocalMediaClicked(object sender, RoutedEventArgs e)
11431145

11441146
try
11451147
{
1148+
// The default start bitrate is quite low (300 kbps); use a higher value to get
1149+
// better quality on local network.
1150+
_peerConnection.SetBitrate(startBitrateBps: (uint)(width * height * framerate / 20));
1151+
11461152
// Add the local audio track captured from the local microphone
11471153
await _peerConnection.AddLocalAudioTrackAsync();
11481154

libs/Microsoft.MixedReality.WebRTC.Native/src/interop/interop_api.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,27 @@ mrsPeerConnectionCreateAnswer(PeerConnectionHandle peerHandle) noexcept {
11961196
return MRS_E_INVALID_PEER_HANDLE;
11971197
}
11981198

1199+
MRS_API mrsResult MRS_CALL mrsPeerConnectionSetBitrate(
1200+
PeerConnectionHandle peer_handle,
1201+
int min_bitrate_bps,
1202+
int start_bitrate_bps,
1203+
int max_bitrate_bps) noexcept {
1204+
if (auto peer = static_cast<PeerConnection*>(peer_handle)) {
1205+
webrtc::BitrateSettings settings;
1206+
if (min_bitrate_bps >= 0) {
1207+
settings.min_bitrate_bps = min_bitrate_bps;
1208+
}
1209+
if (start_bitrate_bps >= 0) {
1210+
settings.start_bitrate_bps = start_bitrate_bps;
1211+
}
1212+
if (max_bitrate_bps >= 0) {
1213+
settings.max_bitrate_bps = max_bitrate_bps;
1214+
}
1215+
return peer->GetImpl()->SetBitrate(settings).ok() ? MRS_SUCCESS : MRS_E_UNKNOWN;
1216+
}
1217+
return MRS_E_INVALID_PEER_HANDLE;
1218+
}
1219+
11991220
mrsResult MRS_CALL
12001221
mrsPeerConnectionSetRemoteDescription(PeerConnectionHandle peerHandle,
12011222
const char* type,

libs/Microsoft.MixedReality.WebRTC.Native/src/interop/interop_api.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,21 @@ mrsPeerConnectionCreateOffer(PeerConnectionHandle peerHandle) noexcept;
601601
MRS_API mrsResult MRS_CALL
602602
mrsPeerConnectionCreateAnswer(PeerConnectionHandle peerHandle) noexcept;
603603

604+
/// Set the bitrate allocated to all RTP streams sent by this connection.
605+
/// Other limitations might affect these limits and are respected (for example
606+
/// "b=AS" in SDP).
607+
///
608+
/// Setting |start_bitrate_bps| will reset the current bitrate estimate to the
609+
/// provided value.
610+
///
611+
/// The values are in bits per second.
612+
/// If any of the arguments has a negative value, it will be ignored.
613+
MRS_API mrsResult MRS_CALL
614+
mrsPeerConnectionSetBitrate(PeerConnectionHandle peer_handle,
615+
int min_bitrate_bps,
616+
int start_bitrate_bps,
617+
int max_bitrate_bps) noexcept;
618+
604619
/// Set a remote description received from a remote peer via the signaling
605620
/// service.
606621
MRS_API mrsResult MRS_CALL

libs/Microsoft.MixedReality.WebRTC.Native/src/pch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "api/mediaconstraintsinterface.h"
4747
#include "api/mediastreaminterface.h"
4848
#include "api/peerconnectioninterface.h"
49+
#include "api/transport/bitrate_settings.h"
4950
#include "api/video/i420_buffer.h"
5051
#include "api/videosourceproxy.h"
5152
#include "media/engine/internaldecoderfactory.h"

libs/Microsoft.MixedReality.WebRTC/Interop/PeerConnectionInterop.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,10 @@ public static extern void PeerConnection_AddIceCandidate(IntPtr peerHandle, stri
587587
EntryPoint = "mrsPeerConnectionCreateAnswer")]
588588
public static extern uint PeerConnection_CreateAnswer(IntPtr peerHandle);
589589

590+
[DllImport(Utils.dllPath, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi,
591+
EntryPoint = "mrsPeerConnectionSetBitrate")]
592+
public static extern uint PeerConnection_SetBitrate(IntPtr peerHandle, int minBitrate, int startBitrate, int maxBitrate);
593+
590594
[DllImport(Utils.dllPath, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi,
591595
EntryPoint = "mrsPeerConnectionSetRemoteDescription")]
592596
public static extern uint PeerConnection_SetRemoteDescription(IntPtr peerHandle, string type, string sdp);

libs/Microsoft.MixedReality.WebRTC/PeerConnection.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,11 +1006,11 @@ public void RemoveLocalAudioTrack()
10061006

10071007
/// <summary>
10081008
/// Add a new out-of-band data channel with the given ID.
1009-
///
1009+
///
10101010
/// A data channel is negotiated out-of-band when the peers agree on an identifier by any mean
10111011
/// not known to WebRTC, and both open a data channel with that ID. The WebRTC will match the
10121012
/// incoming and outgoing pipes by this ID to allow sending and receiving through that channel.
1013-
///
1013+
///
10141014
/// This requires some external mechanism to agree on an available identifier not otherwise taken
10151015
/// by another channel, and also requires to ensure that both peers explicitly open that channel.
10161016
/// </summary>
@@ -1035,13 +1035,13 @@ public async Task<DataChannel> AddDataChannelAsync(ushort id, string label, bool
10351035

10361036
/// <summary>
10371037
/// Add a new in-band data channel whose ID will be determined by the implementation.
1038-
///
1038+
///
10391039
/// A data channel is negotiated in-band when one peer requests its creation to the WebRTC core,
10401040
/// and the implementation negotiates with the remote peer an appropriate ID by sending some
10411041
/// SDP offer message. In that case once accepted the other peer will automatically create the
10421042
/// appropriate data channel on its side with that negotiated ID, and the ID will be returned on
10431043
/// both sides to the user for information.
1044-
///
1044+
///
10451045
/// Compares to out-of-band messages, this requires exchanging some SDP messages, but avoids having
10461046
/// to determine a common unused ID and having to explicitly open the data channel on both sides.
10471047
/// </summary>
@@ -1159,10 +1159,29 @@ public bool CreateAnswer()
11591159
return (PeerConnectionInterop.PeerConnection_CreateAnswer(_nativePeerhandle) == Utils.MRS_SUCCESS);
11601160
}
11611161

1162+
/// <summary>
1163+
/// Set the bitrate allocated to all RTP streams sent by this connection.
1164+
/// Other limitations might affect these limits and are respected (for example
1165+
/// "b=AS" in SDP).
1166+
/// </summary>
1167+
/// <param name="minBitrateBps">Minimum bitrate in bits per second.</param>
1168+
/// <param name="startBitrateBps">Start/current target bitrate in bits per second.</param>
1169+
/// <param name="maxBitrateBps">Maximum bitrate in bits per second.</param>
1170+
public void SetBitrate(uint? minBitrateBps = null, uint? startBitrateBps = null, uint? maxBitrateBps = null)
1171+
{
1172+
ThrowIfConnectionNotOpen();
1173+
int signedMinBitrateBps = minBitrateBps.HasValue ? (int)minBitrateBps.Value : -1;
1174+
int signedStartBitrateBps = startBitrateBps.HasValue ? (int)startBitrateBps.Value : -1;
1175+
int signedMaxBitrateBps = maxBitrateBps.HasValue ? (int)maxBitrateBps.Value : -1;
1176+
uint res = PeerConnectionInterop.PeerConnection_SetBitrate(_nativePeerhandle,
1177+
signedMinBitrateBps, signedStartBitrateBps, signedMaxBitrateBps);
1178+
Utils.ThrowOnErrorCode(res);
1179+
}
1180+
11621181
/// <summary>
11631182
/// Pass the given SDP description received from the remote peer via signaling to the
11641183
/// underlying WebRTC implementation, which will parse and use it.
1165-
///
1184+
///
11661185
/// This must be called by the signaler when receiving a message.
11671186
/// </summary>
11681187
/// <param name="type">The type of SDP message ("offer", "answer", "ice")</param>

0 commit comments

Comments
 (0)