Skip to content

Commit

Permalink
Add AV1 support to load-test client (#825)
Browse files Browse the repository at this point in the history
  • Loading branch information
streamer45 authored Jul 30, 2024
1 parent 06968c0 commit d505f21
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 36 deletions.
99 changes: 84 additions & 15 deletions lt/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"bytes"
"context"
"encoding/binary"
"encoding/json"
"errors"
"fmt"
"io"
"log/slog"
"net/http"
"os"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -46,6 +48,17 @@ var (
{Type: "nack", Parameter: "pli"},
},
}
rtpVideoCodecAV1 = webrtc.RTPCodecCapability{
MimeType: webrtc.MimeTypeAV1,
ClockRate: 90000,
SDPFmtpLine: "",
RTCPFeedback: []webrtc.RTCPFeedback{
{Type: "goog-remb", Parameter: ""},
{Type: "ccm", Parameter: "fir"},
{Type: "nack", Parameter: ""},
{Type: "nack", Parameter: "pli"},
},
}
rtpVideoExtensions = []string{
"urn:ietf:params:rtp-hdrext:sdes:mid",
"urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id",
Expand Down Expand Up @@ -146,19 +159,28 @@ func (u *User) sendVideoFile(track *webrtc.TrackLocalStaticRTP, trx *webrtc.RTPT
return 0
}

var payloader rtp.Payloader
payloader = &codecs.VP8Payloader{
EnablePictureID: true,
}
filename := fmt.Sprintf("./samples/screen_%s.ivf", track.RID())
if track.Codec().MimeType == webrtc.MimeTypeAV1 {
u.log.Info("sending AV1 screen track")
payloader = &codecs.AV1Payloader{}
filename = fmt.Sprintf("./samples/screen_av1_%s.ivf", track.RID())
}

packetizer := rtp.NewPacketizer(
sendMTU,
0,
0,
&codecs.VP8Payloader{
EnablePictureID: true,
},
payloader,
rtp.NewRandomSequencer(),
rtpVideoCodecVP8.ClockRate,
track.Codec().ClockRate,
)

// Open a IVF file and start reading using our IVFReader
file, ivfErr := os.Open(fmt.Sprintf("./samples/screen_%s.ivf", track.RID()))
file, ivfErr := os.Open(filename)
if ivfErr != nil {
u.log.Error(ivfErr.Error())
os.Exit(1)
Expand Down Expand Up @@ -201,7 +223,7 @@ func (u *User) sendVideoFile(track *webrtc.TrackLocalStaticRTP, trx *webrtc.RTPT
os.Exit(1)
}

packets := packetizer.Packetize(frame, rtpVideoCodecVP8.ClockRate/header.TimebaseDenominator)
packets := packetizer.Packetize(frame, track.Codec().ClockRate/header.TimebaseDenominator)
for _, p := range packets {
if u.callsConfig["EnableSimulcast"].(bool) {
if err := p.Header.SetExtension(getExtensionID(rtpVideoExtensions[0]), []byte(trx.Mid())); err != nil {
Expand All @@ -224,7 +246,15 @@ func (u *User) sendVideoFile(track *webrtc.TrackLocalStaticRTP, trx *webrtc.RTPT
func (u *User) transmitScreen() {
streamID := model.NewId()

trackHigh, err := webrtc.NewTrackLocalStaticRTP(rtpVideoCodecVP8, "video", streamID, webrtc.WithRTPStreamID(simulcastLevelHigh))
enableSimulcast, _ := u.callsConfig["EnableSimulcast"].(bool)
enableAV1, _ := u.callsConfig["EnableAV1"].(bool)

rtpVideoCodec := rtpVideoCodecVP8
if enableAV1 && !enableSimulcast {
rtpVideoCodec = rtpVideoCodecAV1
}

trackHigh, err := webrtc.NewTrackLocalStaticRTP(rtpVideoCodec, "video", streamID, webrtc.WithRTPStreamID(simulcastLevelHigh))
if err != nil {
u.log.Error(err.Error())
os.Exit(1)
Expand All @@ -233,7 +263,7 @@ func (u *User) transmitScreen() {
tracks := []webrtc.TrackLocal{trackHigh}

var trackLow *webrtc.TrackLocalStaticRTP
if u.callsConfig["EnableSimulcast"].(bool) {
if enableSimulcast {
trackLow, err = webrtc.NewTrackLocalStaticRTP(rtpVideoCodecVP8, "video", streamID, webrtc.WithRTPStreamID(simulcastLevelLow))
if err != nil {
u.log.Error(err.Error())
Expand All @@ -248,8 +278,21 @@ func (u *User) transmitScreen() {
os.Exit(1)
}

if u.callsConfig["EnableSimulcast"].(bool) {
if enableSimulcast {
go u.sendVideoFile(trackLow, trx)
} else if enableAV1 {
// Fallback VP8 track
fallbackTrack, err := webrtc.NewTrackLocalStaticRTP(rtpVideoCodecVP8, "video", streamID, webrtc.WithRTPStreamID(simulcastLevelHigh))
if err != nil {
u.log.Error(err.Error())
os.Exit(1)
}
trx2, err := u.callsClient.StartScreenShare([]webrtc.TrackLocal{fallbackTrack})
if err != nil {
u.log.Error(err.Error())
os.Exit(1)
}
go u.sendVideoFile(fallbackTrack, trx2)
}

u.sendVideoFile(trackHigh, trx)
Expand Down Expand Up @@ -443,6 +486,29 @@ func (u *User) onConnect() {
}
}

func (u *User) getCallsConfig() (map[string]any, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
res, err := u.apiClient.DoAPIRequest(ctx, http.MethodGet,
fmt.Sprintf("%s/plugins/com.mattermost.calls/config", u.cfg.SiteURL), "", "")
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
}
defer res.Body.Close()

if res.StatusCode != 200 {
return nil, fmt.Errorf("unexpected response status code %d", res.StatusCode)
}

dec := json.NewDecoder(res.Body)
var config map[string]any
if err := dec.Decode(&config); err != nil {
return nil, fmt.Errorf("failed to decode response: %w", err)
}

return config, nil
}

func (u *User) Connect(stopCh chan struct{}) error {
u.log.Debug("connecting user")

Expand Down Expand Up @@ -524,22 +590,25 @@ func (u *User) Connect(stopCh chan struct{}) error {

u.log.Debug("creating calls client")

callsConfig, err := u.getCallsConfig()
if err != nil {
return fmt.Errorf("failed to get calls config: %w", err)
}
u.callsConfig = callsConfig

enableAV1, _ := u.callsConfig["EnableAV1"].(bool)

callsClient, err := client.New(client.Config{
SiteURL: u.cfg.SiteURL,
AuthToken: apiClient.AuthToken,
ChannelID: u.cfg.ChannelID,
EnableAV1: enableAV1,
}, client.WithLogger(u.log))
if err != nil {
return fmt.Errorf("failed to create calls client: %w", err)
}

callsConfig, err := callsClient.GetCallsConfig()
if err != nil {
return fmt.Errorf("failed to get calls config: %w", err)
}

u.callsClient = callsClient
u.callsConfig = callsConfig

u.log.Debug("connecting to call")

Expand Down
14 changes: 7 additions & 7 deletions lt/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ require (
github.com/aws/aws-sdk-go v1.50.3
github.com/hajimehoshi/go-mp3 v0.3.4
github.com/mattermost/mattermost/server/public v0.0.12
github.com/mattermost/rtcd v0.15.1-0.20240523202535-6de0290d7e68
github.com/mattermost/rtcd v0.16.3-0.20240729135840-0cf4f24d69db
github.com/pion/rtp v1.8.6
github.com/pion/webrtc/v3 v3.2.40
github.com/pion/webrtc/v3 v3.2.41
gopkg.in/hraban/opus.v2 v2.0.0-20230925203106-0188a62cb302
)

Expand All @@ -29,7 +29,7 @@ require (
github.com/philhofer/fwd v1.1.2 // indirect
github.com/pion/datachannel v1.5.6 // indirect
github.com/pion/dtls/v2 v2.2.11 // indirect
github.com/pion/ice/v2 v2.3.24 // indirect
github.com/pion/ice/v2 v2.3.25 // indirect
github.com/pion/interceptor v0.1.29 // indirect
github.com/pion/logging v0.2.2 // indirect
github.com/pion/mdns v0.0.12 // indirect
Expand All @@ -49,10 +49,10 @@ require (
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wiggin77/merror v1.0.5 // indirect
github.com/wiggin77/srslog v1.0.1 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
28 changes: 14 additions & 14 deletions lt/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ github.com/mattermost/logr/v2 v2.0.21 h1:CMHsP+nrbRlEC4g7BwOk1GAnMtHkniFhlSQPXy5
github.com/mattermost/logr/v2 v2.0.21/go.mod h1:kZkB/zqKL9e+RY5gB3vGpsyenC+TpuiOenjMkvJJbzc=
github.com/mattermost/mattermost/server/public v0.0.12 h1:iunc9q4/XkArOrndEUn73uFw6v9TOEXEtp6Nm6Iv218=
github.com/mattermost/mattermost/server/public v0.0.12/go.mod h1:Bk+atJcELCIk9Yeq5FoqTr+gra9704+X4amrlwlTgSc=
github.com/mattermost/rtcd v0.15.1-0.20240523202535-6de0290d7e68 h1:MwyRjQWEd/Dxf7DQY33wICVayx/7JrCpwrCbCd3TdNg=
github.com/mattermost/rtcd v0.15.1-0.20240523202535-6de0290d7e68/go.mod h1:Y2s7xaNdsySgUh3jF5GD9/qWK+gsDY3XRF6jDOpo0bY=
github.com/mattermost/rtcd v0.16.3-0.20240729135840-0cf4f24d69db h1:qY/jn7EBLoXuBcGcuueAWHEHCQ78/GQObeo6onOhVkg=
github.com/mattermost/rtcd v0.16.3-0.20240729135840-0cf4f24d69db/go.mod h1:bpGyHeb+JDkDzbrQheenpbrqfPhphW0jr09Jh+rpmpY=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand All @@ -106,8 +106,8 @@ github.com/pion/datachannel v1.5.6/go.mod h1:1eKT6Q85pRnr2mHiWHxJwO50SfZRtWHTsNI
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
github.com/pion/dtls/v2 v2.2.11 h1:9U/dpCYl1ySttROPWJgqWKEylUdT0fXp/xst6JwY5Ks=
github.com/pion/dtls/v2 v2.2.11/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
github.com/pion/ice/v2 v2.3.24 h1:RYgzhH/u5lH0XO+ABatVKCtRd+4U1GEaCXSMjNr13tI=
github.com/pion/ice/v2 v2.3.24/go.mod h1:KXJJcZK7E8WzrBEYnV4UtqEZsGeWfHxsNqhVcVvgjxw=
github.com/pion/ice/v2 v2.3.25 h1:M5rJA07dqhi3nobJIg+uPtcVjFECTrhcR3n0ns8kDZs=
github.com/pion/ice/v2 v2.3.25/go.mod h1:KXJJcZK7E8WzrBEYnV4UtqEZsGeWfHxsNqhVcVvgjxw=
github.com/pion/interceptor v0.1.29 h1:39fsnlP1U8gw2JzOFWdfCU82vHvhW9o0rZnZF56wF+M=
github.com/pion/interceptor v0.1.29/go.mod h1:ri+LGNjRUc5xUNtDEPzfdkmSqISixVTBF/z/Zms/6T4=
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
Expand Down Expand Up @@ -143,8 +143,8 @@ github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37
github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc=
github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
github.com/pion/webrtc/v3 v3.2.40 h1:Wtfi6AZMQg+624cvCXUuSmrKWepSB7zfgYDOYqsSOVU=
github.com/pion/webrtc/v3 v3.2.40/go.mod h1:M1RAe3TNTD1tzyvqHrbVODfwdPGSXOUo/OgpoGGJqFY=
github.com/pion/webrtc/v3 v3.2.41 h1:bz6GxA2bk247YI+uwd9m9Jw3bwSL7g7k0xkBZnl/mF4=
github.com/pion/webrtc/v3 v3.2.41/go.mod h1:M1RAe3TNTD1tzyvqHrbVODfwdPGSXOUo/OgpoGGJqFY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down Expand Up @@ -221,8 +221,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand All @@ -249,8 +249,8 @@ golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand Down Expand Up @@ -283,8 +283,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
Expand All @@ -304,8 +304,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
Binary file added lt/samples/screen_av1_h.ivf
Binary file not shown.

0 comments on commit d505f21

Please sign in to comment.