Skip to content

Commit

Permalink
feat: update Broadcast and SIP (#233)
Browse files Browse the repository at this point in the history
* Add HlsStatus property on Broadcast

* Add MaxBitRate property

* Make Broadcast Bitrate an object with its own validation

* Update converter for Bitrate

* Add streams property to Dial feature

* Add streams property to Dial feature
  • Loading branch information
Tr00d authored Jan 12, 2024
1 parent 186e02e commit f3de99a
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 12 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -220,5 +220,5 @@ pip-log.txt
#Samples/HelloWorld/App.config
#Samples/Archiving/App.config

## Jetbrains IDE
.idea/
## Jetbrains Rider files
.idea/
20 changes: 18 additions & 2 deletions OpenTok/Broadcast.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Expand Down Expand Up @@ -92,6 +91,7 @@ internal void CopyBroadcast(Broadcast broadcast)
StreamMode = broadcast.StreamMode;
Settings = broadcast.Settings;
MultiBroadcastTag = broadcast.MultiBroadcastTag;
MaxBitRate = broadcast.MaxBitRate;

if (BroadcastUrls == null)
return;
Expand All @@ -100,6 +100,11 @@ internal void CopyBroadcast(Broadcast broadcast)
{
Hls = BroadcastUrls["hls"].ToString();
}

if (BroadcastUrls.ContainsKey("hlsStatus"))
{
HlsStatus = BroadcastUrls["hlsStatus"].ToString();
}

if (BroadcastUrls.ContainsKey("rtmp"))
{
Expand Down Expand Up @@ -201,6 +206,17 @@ internal void CopyBroadcast(Broadcast broadcast)
[JsonProperty("multiBroadcastTag")]
public string MultiBroadcastTag { get; set; }

/// <summary>
/// HLS status. Can be one of the following: 'connecting', 'ready', 'live', 'ended' or 'error'.
/// </summary>
public string HlsStatus { get; set; }

/// <summary>
/// Maximum BitRate allowed for the broadcast composing. The default value is 2000000, which is also the maximum value. The minimum value is 400000.
/// </summary>
[JsonConverter(typeof(BroadcastBitrateConverter))]
public BroadcastBitrate MaxBitRate { get; set; } = new BroadcastBitrate();

/// <summary>
/// Stops the live broadcasting if it is started.
/// </summary>
Expand Down
53 changes: 53 additions & 0 deletions OpenTok/BroadcastBitrate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using Newtonsoft.Json;
using OpenTokSDK.Exception;

namespace OpenTokSDK
{
/// <summary>
/// Represents a BitRate for broadcasts.
/// </summary>
public class BroadcastBitrate
{
private const int MaxBitrate = 2000000;
private const int MinBitrate = 400000;

/// <summary>
/// The maximum BitRate allowed for the broadcast composing.
/// </summary>
public long Bitrate { get; }

/// <summary>
/// Creates a BroadcastBitrate with the maximum BitRate.
/// </summary>
public BroadcastBitrate() => this.Bitrate = MaxBitrate;

/// <summary>
/// Creates a BroadcastBitrate with a specific Bitrate.
/// </summary>
/// <param name="bitrate">The Bitrate.</param>
/// <exception cref="OpenTokArgumentException">
/// When specified bitrate is lower than the minimum value, or higher than the
/// maximum value.
/// </exception>
public BroadcastBitrate(long bitrate) =>
this.Bitrate = ValidateBitrate(bitrate)
? bitrate
: throw new OpenTokArgumentException($"Bitrate value must be between {MinBitrate} and {MaxBitrate}.");

private static bool ValidateBitrate(long bitrate) => bitrate <= MaxBitrate && bitrate >= MinBitrate;
}

internal class BroadcastBitrateConverter : JsonConverter<BroadcastBitrate>
{
public override void WriteJson(JsonWriter writer, BroadcastBitrate value, JsonSerializer serializer) =>
writer.WriteValue(value?.Bitrate);

public override BroadcastBitrate ReadJson(JsonReader reader, Type objectType, BroadcastBitrate existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
var value = (long?)reader.Value;
return value.HasValue ? new BroadcastBitrate(value.Value) : null;
}
}
}
5 changes: 5 additions & 0 deletions OpenTok/DialOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,10 @@ public class DialOptions
/// (true) or not (false, the default).
/// </summary>
public bool? ObserveForceMute { get; set; }

/// <summary>
/// The stream IDs of the participants' which will be subscribed by the SIP participant. If not provided, all streams in session will be selected.
/// </summary>
public string[] Streams { get; set; }
}
}
6 changes: 4 additions & 2 deletions OpenTok/OpenTok.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1909,7 +1909,8 @@ public Sip Dial(string sessionId, string token, string sipUri, DialOptions optio
auth = options?.Auth,
secure = options?.Secure,
video = options?.Video,
observeForceMute = options?.ObserveForceMute
observeForceMute = options?.ObserveForceMute,
streams = options?.Streams,
}
}
};
Expand Down Expand Up @@ -1968,7 +1969,8 @@ public async Task<Sip> DialAsync(string sessionId, string token, string sipUri,
auth = options?.Auth,
secure = options?.Secure,
video = options?.Video,
observeForceMute = options?.ObserveForceMute
observeForceMute = options?.ObserveForceMute,
streams = options?.Streams,
}
}
};
Expand Down
30 changes: 30 additions & 0 deletions OpenTokTest/BroadcastBitrateTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using OpenTokSDK;
using OpenTokSDK.Exception;
using Xunit;

namespace OpenTokSDKTest
{
public class BroadcastBitrateTest
{
[Fact]
public void Bitrate_ShouldHaveDefaultValue() =>
Assert.Equal(2000000, new BroadcastBitrate().Bitrate);

[Fact]
public void Bitrate_ShouldAllowMaximumValue()=>
Assert.Equal(2000000, new BroadcastBitrate(2000000).Bitrate);

[Fact]
public void Bitrate_ShouldAllowMinimumValue()=>
Assert.Equal(400000, new BroadcastBitrate(400000).Bitrate);

[Theory]
[InlineData(399999)]
[InlineData(2000001)]
public void Bitrate_ShouldThrowException_GivenValueIsOutsideRange(int invalidBitrate)
{
var exception = Assert.Throws<OpenTokArgumentException>(() => new BroadcastBitrate(invalidBitrate));
Assert.Equal("Bitrate value must be between 400000 and 2000000.", exception.Message);
}
}
}
6 changes: 6 additions & 0 deletions OpenTokTest/BroadcastTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public void StartBroadcast()
Assert.Equal(sessionId, broadcast.SessionId);
Assert.NotNull(broadcast.Id);
Assert.Equal(Broadcast.BroadcastStatus.STARTED, broadcast.Status);
Assert.Equal(2000000, broadcast.MaxBitRate.Bitrate);

mockClient.Verify(
httpClient => httpClient.Post(It.Is<string>(url => url.Equals("v2/project/" + ApiKey + "/broadcast")),
Expand Down Expand Up @@ -57,6 +58,7 @@ public async Task StartBroadcastAsync()
Assert.Equal(sessionId, broadcast.SessionId);
Assert.NotNull(broadcast.Id);
Assert.Equal(Broadcast.BroadcastStatus.STARTED, broadcast.Status);
Assert.Equal(1000000, broadcast.MaxBitRate.Bitrate);

mockClient.Verify(
httpClient => httpClient.PostAsync(expectedUrl, It.IsAny<Dictionary<string, string>>(),
Expand Down Expand Up @@ -481,6 +483,7 @@ public void StartBroadcastWithRTMPandHLS()
Assert.NotNull(broadcast.RtmpList);
Assert.Equal(2, broadcast.RtmpList.Count);
Assert.NotNull(broadcast.Hls);
Assert.Equal("ready", broadcast.HlsStatus);
Assert.NotNull(broadcast.Id);
Assert.Equal(Broadcast.BroadcastStatus.STARTED, broadcast.Status);

Expand Down Expand Up @@ -530,6 +533,7 @@ public async Task StartBroadcastWithRTMPandHLSAsync()
Assert.NotNull(broadcast.RtmpList);
Assert.Equal(2, broadcast.RtmpList.Count);
Assert.NotNull(broadcast.Hls);
Assert.Equal("ready", broadcast.HlsStatus);
Assert.NotNull(broadcast.Id);
Assert.Equal(Broadcast.BroadcastStatus.STARTED, broadcast.Status);

Expand Down Expand Up @@ -1405,6 +1409,7 @@ public void GetBroadcast()
Assert.NotNull(broadcast);
Assert.Equal(broadcastId, broadcast.Id);
Assert.NotNull(broadcast.Id);
Assert.Equal("ready", broadcast.HlsStatus);

var expectedUrl = $"v2/project/{ApiKey}/broadcast/{broadcastId}";
mockClient.Verify(httpClient => httpClient.Get(It.Is<string>(url => url.Equals(expectedUrl))),
Expand All @@ -1427,6 +1432,7 @@ public async Task GetBroadcastAsync()
Assert.NotNull(broadcast);
Assert.Equal(broadcastId, broadcast.Id);
Assert.NotNull(broadcast.Id);
Assert.Equal("ready", broadcast.HlsStatus);

var expectedUrl = $"v2/project/{ApiKey}/broadcast/{broadcastId}";
mockClient.Verify(httpClient => httpClient.GetAsync(It.Is<string>(url => url.Equals(expectedUrl)), null),
Expand Down
3 changes: 2 additions & 1 deletion OpenTokTest/Data/BroadcastTests/GetBroadcast-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"resolution": "640x480",
"status": "started",
"broadcastUrls": {
"hls": "http://server/fakepath/playlist.m3u8"
"hls": "http://server/fakepath/playlist.m3u8",
"hlsStatus" : "ready"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"resolution": "640x480",
"status": "started",
"broadcastUrls": {
"hls": "http://server/fakepath/playlist.m3u8"
"hls": "http://server/fakepath/playlist.m3u8",
"hlsStatus" : "ready"
}
}
3 changes: 2 additions & 1 deletion OpenTokTest/Data/BroadcastTests/StartBroadcast-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
"broadcastUrls": {
"hls": "http://server/fakepath/playlist.m3u8"
},
"settings": { "hls": { "lowLatency": false } }
"settings": { "hls": { "lowLatency": false } },
"maxBitRate": 2000000
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
"broadcastUrls": {
"hls": "http://server/fakepath/playlist.m3u8"
},
"settings": { "hls": { "lowLatency": false } }
"settings": { "hls": { "lowLatency": false } },
"maxBitRate": 1000000
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"status": "started",
"broadcastUrls": {
"hls": "http://server/fakepath/playlist.m3u8",
"hlsStatus" : "ready",
"rtmp": [
{
"status": "connecting",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"status": "started",
"broadcastUrls": {
"hls": "http://server/fakepath/playlist.m3u8",
"hlsStatus" : "ready",
"rtmp": [
{
"status": "connecting",
Expand Down
8 changes: 6 additions & 2 deletions OpenTokTest/DialTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ public void DialCorrectData()
Auth = new DialAuth { Username = "Tim", Password = "Bob" },
Secure = true,
Video = true,
ObserveForceMute = true
ObserveForceMute = true,
Streams = new []{"stream1", "stream2"},
};

Dictionary<string, string> headersSent = null;
Expand Down Expand Up @@ -199,6 +200,7 @@ public void DialCorrectData()
Assert.Equal(dialOptions.Secure, sip.secure);
Assert.Equal(dialOptions.Video, sip.video);
Assert.Equal(dialOptions.ObserveForceMute, sip.observeForceMute);
Assert.Equal(dialOptions.Streams, sip.streams);
}

[Fact]
Expand All @@ -215,7 +217,8 @@ public async Task DialAsyncCorrectData()
Auth = new DialAuth { Username = "Tim", Password = "Bob" },
Secure = true,
Video = true,
ObserveForceMute = true
ObserveForceMute = true,
Streams = new []{"stream1", "stream2"},
};

Dictionary<string, string> headersSent = null;
Expand Down Expand Up @@ -250,6 +253,7 @@ public async Task DialAsyncCorrectData()
Assert.Equal(dialOptions.Secure, sip.secure);
Assert.Equal(dialOptions.Video, sip.video);
Assert.Equal(dialOptions.ObserveForceMute, sip.observeForceMute);
Assert.Equal(dialOptions.Streams, sip.streams);
}

[Fact]
Expand Down

0 comments on commit f3de99a

Please sign in to comment.