mirror of
https://github.com/livekit/livekit.git
synced 2026-03-30 15:35:41 +00:00
893 lines
24 KiB
Go
893 lines
24 KiB
Go
// Copyright 2023 LiveKit, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package buffer
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/livekit/protocol/codecs/mime"
|
|
"github.com/livekit/protocol/livekit"
|
|
)
|
|
|
|
func TestRidConversion(t *testing.T) {
|
|
type RidAndLayer struct {
|
|
rid string
|
|
layer int32
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
trackInfo *livekit.TrackInfo
|
|
mimeType mime.MimeType
|
|
ridToLayer map[string]RidAndLayer
|
|
}{
|
|
{
|
|
"no track info",
|
|
nil,
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: halfResolutionH, layer: 1},
|
|
fullResolutionF: {rid: fullResolutionF, layer: 2},
|
|
},
|
|
},
|
|
{
|
|
"no layers",
|
|
&livekit.TrackInfo{},
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: halfResolutionH, layer: 1},
|
|
fullResolutionF: {rid: fullResolutionF, layer: 2},
|
|
},
|
|
},
|
|
{
|
|
"single layer, low",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: quarterResolutionQ, layer: 0},
|
|
fullResolutionF: {rid: quarterResolutionQ, layer: 0},
|
|
},
|
|
},
|
|
{
|
|
"single layer, medium",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: quarterResolutionQ, layer: 0},
|
|
fullResolutionF: {rid: quarterResolutionQ, layer: 0},
|
|
},
|
|
},
|
|
{
|
|
"single layer, high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: quarterResolutionQ, layer: 0},
|
|
fullResolutionF: {rid: quarterResolutionQ, layer: 0},
|
|
},
|
|
},
|
|
{
|
|
"two layers, low and medium",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: halfResolutionH, layer: 1},
|
|
fullResolutionF: {rid: halfResolutionH, layer: 1},
|
|
},
|
|
},
|
|
{
|
|
"two layers, low and high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: halfResolutionH, layer: 1},
|
|
fullResolutionF: {rid: halfResolutionH, layer: 1},
|
|
},
|
|
},
|
|
{
|
|
"two layers, medium and high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: halfResolutionH, layer: 1},
|
|
fullResolutionF: {rid: halfResolutionH, layer: 1},
|
|
},
|
|
},
|
|
{
|
|
"three layers",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]RidAndLayer{
|
|
"": {rid: quarterResolutionQ, layer: 0},
|
|
quarterResolutionQ: {rid: quarterResolutionQ, layer: 0},
|
|
halfResolutionH: {rid: halfResolutionH, layer: 1},
|
|
fullResolutionF: {rid: fullResolutionF, layer: 2},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
for testRid, expectedResult := range test.ridToLayer {
|
|
actualLayer := RidToSpatialLayer(test.mimeType, testRid, test.trackInfo, DefaultVideoLayersRid)
|
|
require.Equal(t, expectedResult.layer, actualLayer)
|
|
|
|
actualRid := SpatialLayerToRid(test.mimeType, actualLayer, test.trackInfo, DefaultVideoLayersRid)
|
|
require.Equal(t, expectedResult.rid, actualRid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestQualityConversion(t *testing.T) {
|
|
type QualityAndLayer struct {
|
|
quality livekit.VideoQuality
|
|
layer int32
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
trackInfo *livekit.TrackInfo
|
|
mimeType mime.MimeType
|
|
qualityToLayer map[livekit.VideoQuality]QualityAndLayer
|
|
}{
|
|
{
|
|
"no track info",
|
|
nil,
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_LOW, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_MEDIUM, layer: 1},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_HIGH, layer: 2},
|
|
},
|
|
},
|
|
{
|
|
"no layers",
|
|
&livekit.TrackInfo{},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_LOW, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_MEDIUM, layer: 1},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_HIGH, layer: 2},
|
|
},
|
|
},
|
|
{
|
|
"single layer, low",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_LOW, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_LOW, layer: 0},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_LOW, layer: 0},
|
|
},
|
|
},
|
|
{
|
|
"single layer, medium",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_MEDIUM, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_MEDIUM, layer: 0},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_MEDIUM, layer: 0},
|
|
},
|
|
},
|
|
{
|
|
"single layer, high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_HIGH, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_HIGH, layer: 0},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_HIGH, layer: 0},
|
|
},
|
|
},
|
|
{
|
|
"two layers, low and medium",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_LOW, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_MEDIUM, layer: 1},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_MEDIUM, layer: 1},
|
|
},
|
|
},
|
|
{
|
|
"two layers, low and high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_LOW, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_HIGH, layer: 1},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_HIGH, layer: 1},
|
|
},
|
|
},
|
|
{
|
|
"two layers, medium and high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_MEDIUM, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_MEDIUM, layer: 0},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_HIGH, layer: 1},
|
|
},
|
|
},
|
|
{
|
|
"three layers",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]QualityAndLayer{
|
|
livekit.VideoQuality_LOW: {quality: livekit.VideoQuality_LOW, layer: 0},
|
|
livekit.VideoQuality_MEDIUM: {quality: livekit.VideoQuality_MEDIUM, layer: 1},
|
|
livekit.VideoQuality_HIGH: {quality: livekit.VideoQuality_HIGH, layer: 2},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
for testQuality, expectedResult := range test.qualityToLayer {
|
|
actualLayer := VideoQualityToSpatialLayer(test.mimeType, testQuality, test.trackInfo)
|
|
require.Equal(t, expectedResult.layer, actualLayer)
|
|
|
|
actualQuality := SpatialLayerToVideoQuality(test.mimeType, actualLayer, test.trackInfo)
|
|
require.Equal(t, expectedResult.quality, actualQuality)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVideoQualityToRidConversion(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
trackInfo *livekit.TrackInfo
|
|
mimeTye mime.MimeType
|
|
qualityToRid map[livekit.VideoQuality]string
|
|
}{
|
|
{
|
|
"no track info",
|
|
nil,
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: halfResolutionH,
|
|
livekit.VideoQuality_HIGH: fullResolutionF,
|
|
},
|
|
},
|
|
{
|
|
"no layers",
|
|
&livekit.TrackInfo{},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: halfResolutionH,
|
|
livekit.VideoQuality_HIGH: fullResolutionF,
|
|
},
|
|
},
|
|
{
|
|
"single layer, low",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: quarterResolutionQ,
|
|
livekit.VideoQuality_HIGH: quarterResolutionQ,
|
|
},
|
|
},
|
|
{
|
|
"single layer, medium",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: quarterResolutionQ,
|
|
livekit.VideoQuality_HIGH: quarterResolutionQ,
|
|
},
|
|
},
|
|
{
|
|
"single layer, high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: quarterResolutionQ,
|
|
livekit.VideoQuality_HIGH: quarterResolutionQ,
|
|
},
|
|
},
|
|
{
|
|
"two layers, low and medium",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: halfResolutionH,
|
|
livekit.VideoQuality_HIGH: halfResolutionH,
|
|
},
|
|
},
|
|
{
|
|
"two layers, low and high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: halfResolutionH,
|
|
livekit.VideoQuality_HIGH: halfResolutionH,
|
|
},
|
|
},
|
|
{
|
|
"two layers, medium and high",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: quarterResolutionQ,
|
|
livekit.VideoQuality_HIGH: halfResolutionH,
|
|
},
|
|
},
|
|
{
|
|
"three layers",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW},
|
|
{Quality: livekit.VideoQuality_MEDIUM},
|
|
{Quality: livekit.VideoQuality_HIGH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]string{
|
|
livekit.VideoQuality_LOW: quarterResolutionQ,
|
|
livekit.VideoQuality_MEDIUM: halfResolutionH,
|
|
livekit.VideoQuality_HIGH: fullResolutionF,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
for testQuality, expectedRid := range test.qualityToRid {
|
|
actualRid := VideoQualityToRid(test.mimeTye, testQuality, test.trackInfo, DefaultVideoLayersRid)
|
|
require.Equal(t, expectedRid, actualRid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetSpatialLayerForRid(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
trackInfo *livekit.TrackInfo
|
|
mimeType mime.MimeType
|
|
ridToSpatialLayer map[string]int32
|
|
}{
|
|
{
|
|
"no track info",
|
|
nil,
|
|
mime.MimeTypeVP8,
|
|
map[string]int32{
|
|
quarterResolutionQ: InvalidLayerSpatial,
|
|
halfResolutionH: InvalidLayerSpatial,
|
|
fullResolutionF: InvalidLayerSpatial,
|
|
},
|
|
},
|
|
{
|
|
"no layers",
|
|
&livekit.TrackInfo{},
|
|
mime.MimeTypeVP8,
|
|
map[string]int32{
|
|
// SIMULCAST-CODEC-TODO
|
|
// quarterResolutionQ: InvalidLayerSpatial,
|
|
// halfResolutionH: InvalidLayerSpatial,
|
|
// fullResolutionF: InvalidLayerSpatial,
|
|
quarterResolutionQ: 0,
|
|
halfResolutionH: 0,
|
|
fullResolutionF: 0,
|
|
},
|
|
},
|
|
{
|
|
"no rid",
|
|
&livekit.TrackInfo{},
|
|
mime.MimeTypeVP8,
|
|
map[string]int32{
|
|
"": 0,
|
|
},
|
|
},
|
|
{
|
|
"single layer",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW, SpatialLayer: 0},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]int32{
|
|
quarterResolutionQ: 0,
|
|
halfResolutionH: 0,
|
|
fullResolutionF: 0,
|
|
},
|
|
},
|
|
{
|
|
"layers",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW, SpatialLayer: 0, Rid: quarterResolutionQ},
|
|
{Quality: livekit.VideoQuality_MEDIUM, SpatialLayer: 1, Rid: halfResolutionH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]int32{
|
|
quarterResolutionQ: 0,
|
|
halfResolutionH: 1,
|
|
// SIMULCAST-CODEC-TODO
|
|
// fullResolutionF: InvalidLayerSpatial,
|
|
fullResolutionF: 0,
|
|
},
|
|
},
|
|
{
|
|
"layers - no rid",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW, SpatialLayer: 0},
|
|
{Quality: livekit.VideoQuality_MEDIUM, SpatialLayer: 1},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[string]int32{
|
|
quarterResolutionQ: 0,
|
|
halfResolutionH: 0,
|
|
fullResolutionF: 0,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
for testRid, expectedSpatialLayer := range test.ridToSpatialLayer {
|
|
actualSpatialLayer := GetSpatialLayerForRid(test.mimeType, testRid, test.trackInfo)
|
|
require.Equal(t, expectedSpatialLayer, actualSpatialLayer)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetSpatialLayerForVideoQuality(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
trackInfo *livekit.TrackInfo
|
|
mimeType mime.MimeType
|
|
videoQualityToSpatialLayer map[livekit.VideoQuality]int32
|
|
}{
|
|
{
|
|
"no track info",
|
|
nil,
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]int32{
|
|
livekit.VideoQuality_LOW: InvalidLayerSpatial,
|
|
livekit.VideoQuality_MEDIUM: InvalidLayerSpatial,
|
|
livekit.VideoQuality_HIGH: InvalidLayerSpatial,
|
|
livekit.VideoQuality_OFF: InvalidLayerSpatial,
|
|
},
|
|
},
|
|
{
|
|
"no layers",
|
|
&livekit.TrackInfo{},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]int32{
|
|
livekit.VideoQuality_LOW: 0,
|
|
livekit.VideoQuality_MEDIUM: 0,
|
|
livekit.VideoQuality_HIGH: 0,
|
|
livekit.VideoQuality_OFF: InvalidLayerSpatial,
|
|
},
|
|
},
|
|
{
|
|
"not all layers",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW, SpatialLayer: 0, Rid: quarterResolutionQ},
|
|
{Quality: livekit.VideoQuality_MEDIUM, SpatialLayer: 1, Rid: halfResolutionH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]int32{
|
|
livekit.VideoQuality_LOW: 0,
|
|
livekit.VideoQuality_MEDIUM: 1,
|
|
livekit.VideoQuality_HIGH: 1,
|
|
livekit.VideoQuality_OFF: InvalidLayerSpatial,
|
|
},
|
|
},
|
|
{
|
|
"all layers",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW, SpatialLayer: 0, Rid: quarterResolutionQ},
|
|
{Quality: livekit.VideoQuality_MEDIUM, SpatialLayer: 1, Rid: halfResolutionH},
|
|
{Quality: livekit.VideoQuality_HIGH, SpatialLayer: 2, Rid: fullResolutionF},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[livekit.VideoQuality]int32{
|
|
livekit.VideoQuality_LOW: 0,
|
|
livekit.VideoQuality_MEDIUM: 1,
|
|
livekit.VideoQuality_HIGH: 2,
|
|
livekit.VideoQuality_OFF: InvalidLayerSpatial,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
for testVideoQuality, expectedSpatialLayer := range test.videoQualityToSpatialLayer {
|
|
actualSpatialLayer := GetSpatialLayerForVideoQuality(test.mimeType, testVideoQuality, test.trackInfo)
|
|
require.Equal(t, expectedSpatialLayer, actualSpatialLayer)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetVideoQualityorSpatialLayer(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
trackInfo *livekit.TrackInfo
|
|
mimeType mime.MimeType
|
|
spatialLayerToVideoQuality map[int32]livekit.VideoQuality
|
|
}{
|
|
{
|
|
"no track info",
|
|
nil,
|
|
mime.MimeTypeVP8,
|
|
map[int32]livekit.VideoQuality{
|
|
InvalidLayerSpatial: livekit.VideoQuality_OFF,
|
|
0: livekit.VideoQuality_OFF,
|
|
1: livekit.VideoQuality_OFF,
|
|
2: livekit.VideoQuality_OFF,
|
|
},
|
|
},
|
|
{
|
|
"no layers",
|
|
&livekit.TrackInfo{},
|
|
mime.MimeTypeVP8,
|
|
map[int32]livekit.VideoQuality{
|
|
InvalidLayerSpatial: livekit.VideoQuality_OFF,
|
|
0: livekit.VideoQuality_OFF,
|
|
1: livekit.VideoQuality_OFF,
|
|
2: livekit.VideoQuality_OFF,
|
|
},
|
|
},
|
|
{
|
|
"layers",
|
|
&livekit.TrackInfo{
|
|
Codecs: []*livekit.SimulcastCodecInfo{
|
|
{
|
|
MimeType: mime.MimeTypeVP8.String(),
|
|
Layers: []*livekit.VideoLayer{
|
|
{Quality: livekit.VideoQuality_LOW, SpatialLayer: 0, Rid: quarterResolutionQ},
|
|
{Quality: livekit.VideoQuality_MEDIUM, SpatialLayer: 1, Rid: halfResolutionH},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
mime.MimeTypeVP8,
|
|
map[int32]livekit.VideoQuality{
|
|
InvalidLayerSpatial: livekit.VideoQuality_OFF,
|
|
0: livekit.VideoQuality_LOW,
|
|
1: livekit.VideoQuality_MEDIUM,
|
|
2: livekit.VideoQuality_OFF,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
for testSpatialLayer, expectedVideoQuality := range test.spatialLayerToVideoQuality {
|
|
actualVideoQuality := GetVideoQualityForSpatialLayer(test.mimeType, testSpatialLayer, test.trackInfo)
|
|
require.Equal(t, expectedVideoQuality, actualVideoQuality)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNormalizeVideoLayersRid(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
rids VideoLayersRid
|
|
normalized VideoLayersRid
|
|
}{
|
|
{
|
|
"empty",
|
|
VideoLayersRid{},
|
|
VideoLayersRid{},
|
|
},
|
|
{
|
|
"unknown pattern",
|
|
VideoLayersRid{"3", "2", "1"},
|
|
VideoLayersRid{"3", "2", "1"},
|
|
},
|
|
{
|
|
"qhf",
|
|
videoLayersRidQHF,
|
|
videoLayersRidQHF,
|
|
},
|
|
{
|
|
"scrambled qhf",
|
|
VideoLayersRid{"f", "h", "q"},
|
|
videoLayersRidQHF,
|
|
},
|
|
{
|
|
"partial qhf",
|
|
VideoLayersRid{"h", "q"},
|
|
VideoLayersRid{"q", "h", ""},
|
|
},
|
|
{
|
|
"210",
|
|
videoLayersRid210,
|
|
videoLayersRid210,
|
|
},
|
|
{
|
|
"scrambled 210",
|
|
VideoLayersRid{"2", "0", "1"},
|
|
videoLayersRid210,
|
|
},
|
|
{
|
|
"partial 210",
|
|
VideoLayersRid{"1", "2"},
|
|
VideoLayersRid{"2", "1", ""},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
normalizedRids := NormalizeVideoLayersRid(test.rids)
|
|
require.Equal(t, test.normalized, normalizedRids)
|
|
})
|
|
}
|
|
}
|