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

Commit

Permalink
Expose PeerConnectionInterface::SetBitrate (#109)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
fibann authored and djee-ms committed Oct 24, 2019
1 parent 766d27e commit 28dfdf1
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 9 deletions.
14 changes: 10 additions & 4 deletions examples/TestAppUwp/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ private Task RunOnWorkerThread(Action handler)
/// <param name="width">The width of the video in pixels.</param>
/// <param name="height">The height of the video in pixels.</param>
/// <returns>The newly created video source.</returns>
private MediaStreamSource CreateVideoStreamSource(uint width, uint height)
private MediaStreamSource CreateVideoStreamSource(uint width, uint height, uint framerate)
{
if (width == 0)
{
Expand All @@ -720,7 +720,7 @@ private MediaStreamSource CreateVideoStreamSource(uint width, uint height)
// https://docs.microsoft.com/en-us/windows/desktop/medfound/video-subtype-guids
var videoProperties = VideoEncodingProperties.CreateUncompressed(MediaEncodingSubtypes.Iyuv, width, height);
var videoStreamDesc = new VideoStreamDescriptor(videoProperties);
videoStreamDesc.EncodingProperties.FrameRate.Numerator = 30;
videoStreamDesc.EncodingProperties.FrameRate.Numerator = framerate;
videoStreamDesc.EncodingProperties.FrameRate.Denominator = 1;
videoStreamDesc.EncodingProperties.Bitrate = (30 * width * height * 8 * 8 / 12); // 30-fps 8bits/byte NV12=12bpp
var videoStreamSource = new MediaStreamSource(videoStreamDesc);
Expand Down Expand Up @@ -975,8 +975,10 @@ private void Peer_RemoteI420FrameReady(I420AVideoFrame frame)
_isRemoteVideoPlaying = true;
uint width = frame.width;
uint height = frame.height;
// We don't know the remote video framerate yet, so use a default.
uint framerate = 30;
RunOnMainThread(() => {
remoteVideoSource = CreateVideoStreamSource(width, height);
remoteVideoSource = CreateVideoStreamSource(width, height, framerate);
remoteVideoPlayer.Source = MediaSource.CreateFromMediaStreamSource(remoteVideoSource);
remoteVideoPlayer.Play();
});
Expand Down Expand Up @@ -1129,7 +1131,7 @@ private async void StartLocalMediaClicked(object sender, RoutedEventArgs e)
localMediaSource?.Reset();
localVideo.SetMediaPlayer(null);
localVideoSource = null;
localVideoSource = CreateVideoStreamSource(width, height);
localVideoSource = CreateVideoStreamSource(width, height, (uint)framerate);
localMediaSource = MediaSource.CreateFromMediaStreamSource(localVideoSource);
localVideoPlayer.Source = localMediaSource;
localVideo.SetMediaPlayer(localVideoPlayer);
Expand All @@ -1143,6 +1145,10 @@ private async void StartLocalMediaClicked(object sender, RoutedEventArgs e)

try
{
// The default start bitrate is quite low (300 kbps); use a higher value to get
// better quality on local network.
_peerConnection.SetBitrate(startBitrateBps: (uint)(width * height * framerate / 20));

// Add the local audio track captured from the local microphone
await _peerConnection.AddLocalAudioTrackAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,27 @@ mrsPeerConnectionCreateAnswer(PeerConnectionHandle peerHandle) noexcept {
return MRS_E_INVALID_PEER_HANDLE;
}

MRS_API mrsResult MRS_CALL mrsPeerConnectionSetBitrate(
PeerConnectionHandle peer_handle,
int min_bitrate_bps,
int start_bitrate_bps,
int max_bitrate_bps) noexcept {
if (auto peer = static_cast<PeerConnection*>(peer_handle)) {
webrtc::BitrateSettings settings;
if (min_bitrate_bps >= 0) {
settings.min_bitrate_bps = min_bitrate_bps;
}
if (start_bitrate_bps >= 0) {
settings.start_bitrate_bps = start_bitrate_bps;
}
if (max_bitrate_bps >= 0) {
settings.max_bitrate_bps = max_bitrate_bps;
}
return peer->GetImpl()->SetBitrate(settings).ok() ? MRS_SUCCESS : MRS_E_UNKNOWN;
}
return MRS_E_INVALID_PEER_HANDLE;
}

mrsResult MRS_CALL
mrsPeerConnectionSetRemoteDescription(PeerConnectionHandle peerHandle,
const char* type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,21 @@ mrsPeerConnectionCreateOffer(PeerConnectionHandle peerHandle) noexcept;
MRS_API mrsResult MRS_CALL
mrsPeerConnectionCreateAnswer(PeerConnectionHandle peerHandle) noexcept;

/// Set the bitrate allocated to all RTP streams sent by this connection.
/// Other limitations might affect these limits and are respected (for example
/// "b=AS" in SDP).
///
/// Setting |start_bitrate_bps| will reset the current bitrate estimate to the
/// provided value.
///
/// The values are in bits per second.
/// If any of the arguments has a negative value, it will be ignored.
MRS_API mrsResult MRS_CALL
mrsPeerConnectionSetBitrate(PeerConnectionHandle peer_handle,
int min_bitrate_bps,
int start_bitrate_bps,
int max_bitrate_bps) noexcept;

/// Set a remote description received from a remote peer via the signaling
/// service.
MRS_API mrsResult MRS_CALL
Expand Down
1 change: 1 addition & 0 deletions libs/Microsoft.MixedReality.WebRTC.Native/src/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "api/mediaconstraintsinterface.h"
#include "api/mediastreaminterface.h"
#include "api/peerconnectioninterface.h"
#include "api/transport/bitrate_settings.h"
#include "api/video/i420_buffer.h"
#include "api/videosourceproxy.h"
#include "media/engine/internaldecoderfactory.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,10 @@ public static extern void PeerConnection_AddIceCandidate(IntPtr peerHandle, stri
EntryPoint = "mrsPeerConnectionCreateAnswer")]
public static extern uint PeerConnection_CreateAnswer(IntPtr peerHandle);

[DllImport(Utils.dllPath, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi,
EntryPoint = "mrsPeerConnectionSetBitrate")]
public static extern uint PeerConnection_SetBitrate(IntPtr peerHandle, int minBitrate, int startBitrate, int maxBitrate);

[DllImport(Utils.dllPath, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi,
EntryPoint = "mrsPeerConnectionSetRemoteDescription")]
public static extern uint PeerConnection_SetRemoteDescription(IntPtr peerHandle, string type, string sdp);
Expand Down
29 changes: 24 additions & 5 deletions libs/Microsoft.MixedReality.WebRTC/PeerConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,11 +1006,11 @@ public void RemoveLocalAudioTrack()

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

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

/// <summary>
/// Set the bitrate allocated to all RTP streams sent by this connection.
/// Other limitations might affect these limits and are respected (for example
/// "b=AS" in SDP).
/// </summary>
/// <param name="minBitrateBps">Minimum bitrate in bits per second.</param>
/// <param name="startBitrateBps">Start/current target bitrate in bits per second.</param>
/// <param name="maxBitrateBps">Maximum bitrate in bits per second.</param>
public void SetBitrate(uint? minBitrateBps = null, uint? startBitrateBps = null, uint? maxBitrateBps = null)
{
ThrowIfConnectionNotOpen();
int signedMinBitrateBps = minBitrateBps.HasValue ? (int)minBitrateBps.Value : -1;
int signedStartBitrateBps = startBitrateBps.HasValue ? (int)startBitrateBps.Value : -1;
int signedMaxBitrateBps = maxBitrateBps.HasValue ? (int)maxBitrateBps.Value : -1;
uint res = PeerConnectionInterop.PeerConnection_SetBitrate(_nativePeerhandle,
signedMinBitrateBps, signedStartBitrateBps, signedMaxBitrateBps);
Utils.ThrowOnErrorCode(res);
}

/// <summary>
/// Pass the given SDP description received from the remote peer via signaling to the
/// underlying WebRTC implementation, which will parse and use it.
///
///
/// This must be called by the signaler when receiving a message.
/// </summary>
/// <param name="type">The type of SDP message ("offer", "answer", "ice")</param>
Expand Down

0 comments on commit 28dfdf1

Please sign in to comment.