Merge pull request #183 from strukturag/custom-bandwidth

Clients can provide the maximum publishing bandwidth in offer requests.
This commit is contained in:
Joachim Bauch 2022-01-10 15:22:49 +01:00 committed by GitHub
commit d806922764
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 206 additions and 3 deletions

View File

@ -411,6 +411,7 @@ type MessageClientMessageData struct {
Type string `json:"type"`
Sid string `json:"sid"`
RoomType string `json:"roomType"`
Bitrate int `json:"bitrate,omitempty"`
Payload map[string]interface{} `json:"payload"`
}

View File

@ -820,12 +820,18 @@ func (s *ClientSession) GetOrCreatePublisher(ctx context.Context, mcu Mcu, strea
client := s.getClientUnlocked()
s.mu.Unlock()
var bitrate int
bitrate := data.Bitrate
if backend := s.Backend(); backend != nil {
var maxBitrate int
if streamType == streamTypeScreen {
bitrate = backend.maxScreenBitrate
maxBitrate = backend.maxScreenBitrate
} else {
bitrate = backend.maxStreamBitrate
maxBitrate = backend.maxStreamBitrate
}
if bitrate <= 0 {
bitrate = maxBitrate
} else if maxBitrate > 0 && bitrate > maxBitrate {
bitrate = maxBitrate
}
}
var err error

View File

@ -22,6 +22,8 @@
package signaling
import (
"context"
"net/url"
"strconv"
"testing"
)
@ -122,3 +124,179 @@ func Test_permissionsEqual(t *testing.T) {
})
}
}
func TestBandwidth_Client(t *testing.T) {
hub, _, _, server, shutdown := CreateHubForTest(t)
defer shutdown()
mcu, err := NewTestMCU()
if err != nil {
t.Fatal(err)
} else if err := mcu.Start(); err != nil {
t.Fatal(err)
}
defer mcu.Stop()
hub.SetMcu(mcu)
client := NewTestClient(t, server, hub)
defer client.CloseWithBye()
if err := client.SendHello(testDefaultUserId); err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
hello, err := client.RunUntilHello(ctx)
if err != nil {
t.Fatal(err)
}
// Join room by id.
roomId := "test-room"
if room, err := client.JoinRoom(ctx, roomId); err != nil {
t.Fatal(err)
} else if room.Room.RoomId != roomId {
t.Fatalf("Expected room %s, got %s", roomId, room.Room.RoomId)
}
// We will receive a "joined" event.
if err := client.RunUntilJoined(ctx, hello.Hello); err != nil {
t.Error(err)
}
// Client may not send an offer with audio and video.
bitrate := 10000
if err := client.SendMessage(MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: "video",
Bitrate: bitrate,
Payload: map[string]interface{}{
"sdp": MockSdpOfferAudioAndVideo,
},
}); err != nil {
t.Fatal(err)
}
if err := client.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo); err != nil {
t.Fatal(err)
}
pub := mcu.GetPublisher(hello.Hello.SessionId)
if pub == nil {
t.Fatal("Could not find publisher")
}
if pub.bitrate != bitrate {
t.Errorf("Expected bitrate %d, got %d", bitrate, pub.bitrate)
}
}
func TestBandwidth_Backend(t *testing.T) {
hub, _, _, server, shutdown := CreateHubWithMultipleBackendsForTest(t)
defer shutdown()
u, err := url.Parse(server.URL + "/one")
if err != nil {
t.Fatal(err)
}
backend := hub.backend.GetBackend(u)
if backend == nil {
t.Fatal("Could not get backend")
}
backend.maxScreenBitrate = 1000
backend.maxStreamBitrate = 2000
mcu, err := NewTestMCU()
if err != nil {
t.Fatal(err)
} else if err := mcu.Start(); err != nil {
t.Fatal(err)
}
defer mcu.Stop()
hub.SetMcu(mcu)
streamTypes := []string{
streamTypeVideo,
streamTypeScreen,
}
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
defer cancel()
for _, streamType := range streamTypes {
t.Run(streamType, func(t *testing.T) {
client := NewTestClient(t, server, hub)
defer client.CloseWithBye()
params := TestBackendClientAuthParams{
UserId: testDefaultUserId,
}
if err := client.SendHelloParams(server.URL+"/one", "client", params); err != nil {
t.Fatal(err)
}
hello, err := client.RunUntilHello(ctx)
if err != nil {
t.Fatal(err)
}
// Join room by id.
roomId := "test-room"
if room, err := client.JoinRoom(ctx, roomId); err != nil {
t.Fatal(err)
} else if room.Room.RoomId != roomId {
t.Fatalf("Expected room %s, got %s", roomId, room.Room.RoomId)
}
// We will receive a "joined" event.
if err := client.RunUntilJoined(ctx, hello.Hello); err != nil {
t.Error(err)
}
// Client may not send an offer with audio and video.
bitrate := 10000
if err := client.SendMessage(MessageClientMessageRecipient{
Type: "session",
SessionId: hello.Hello.SessionId,
}, MessageClientMessageData{
Type: "offer",
Sid: "54321",
RoomType: streamType,
Bitrate: bitrate,
Payload: map[string]interface{}{
"sdp": MockSdpOfferAudioAndVideo,
},
}); err != nil {
t.Fatal(err)
}
if err := client.RunUntilAnswer(ctx, MockSdpAnswerAudioAndVideo); err != nil {
t.Fatal(err)
}
pub := mcu.GetPublisher(hello.Hello.SessionId)
if pub == nil {
t.Fatal("Could not find publisher")
}
var expectBitrate int
if streamType == streamTypeVideo {
expectBitrate = backend.maxStreamBitrate
} else {
expectBitrate = backend.maxScreenBitrate
}
if pub.bitrate != expectBitrate {
t.Errorf("Expected bitrate %d, got %d", expectBitrate, pub.bitrate)
}
})
}
}

View File

@ -31,6 +31,11 @@ import (
"github.com/dlintw/goconf"
)
const (
TestMaxBitrateScreen = 12345678
TestMaxBitrateVideo = 23456789
)
type TestMCU struct {
mu sync.Mutex
publishers map[string]*TestMCUPublisher
@ -63,6 +68,17 @@ func (m *TestMCU) GetStats() interface{} {
}
func (m *TestMCU) NewPublisher(ctx context.Context, listener McuListener, id string, streamType string, bitrate int, mediaTypes MediaType, initiator McuInitiator) (McuPublisher, error) {
var maxBitrate int
if streamType == streamTypeScreen {
maxBitrate = TestMaxBitrateScreen
} else {
maxBitrate = TestMaxBitrateVideo
}
if bitrate <= 0 {
bitrate = maxBitrate
} else if bitrate > maxBitrate {
bitrate = maxBitrate
}
pub := &TestMCUPublisher{
TestMCUClient: TestMCUClient{
id: id,
@ -70,6 +86,7 @@ func (m *TestMCU) NewPublisher(ctx context.Context, listener McuListener, id str
},
mediaTypes: mediaTypes,
bitrate: bitrate,
}
m.mu.Lock()
@ -129,6 +146,7 @@ type TestMCUPublisher struct {
TestMCUClient
mediaTypes MediaType
bitrate int
}
func (p *TestMCUPublisher) HasMedia(mt MediaType) bool {