Files
AAA cfc323adce feat(media): integrate embedded media services and shared native encoding
Embed STUN and SFU in the shared Go process, reuse native encoding pipelines with independent adaptation, and complete Client lifecycle, settings, diagnostics and packaging fixes. Retain standard Browser senders after measured encoded-reuse limitations.
2026-09-09 06:09:06 +08:00

116 lines
4.1 KiB
Go

package protocol
import "errors"
// SfuMedia describes the publisher's real encodings, ordered low to high.
type SfuMedia struct {
Codec string `json:"codec"`
Layers []SfuLayer `json:"layers"`
Audio bool `json:"audio"`
AudioBitrate Int `json:"audioBitrate"`
}
type SfuLayer struct {
RID string `json:"rid"`
Width Int `json:"width"`
Height Int `json:"height"`
Bitrate Int `json:"bitrate"`
}
func (value *SfuMedia) UnmarshalJSON(data []byte) error {
type raw SfuMedia
present, err := decodeObject(data, (*raw)(value))
if err != nil {
return err
}
if err := present.require("codec", "layers", "audio", "audioBitrate"); err != nil {
return err
}
if !enumOf(value.Codec, "h264", "vp8") || len(value.Layers) < 1 || len(value.Layers) > 3 ||
!inRangeInt(value.AudioBitrate, 0, 510_000) || value.Audio && value.AudioBitrate == 0 {
return errors.New("invalid SFU media")
}
for index, layer := range value.Layers {
if len(layer.RID) > 16 || layer.RID == "" && len(value.Layers) != 1 ||
!inRangeInt(layer.Width, 1, 8192) || !inRangeInt(layer.Height, 1, 8192) || !inRangeInt(layer.Bitrate, 1, 100_000_000) {
return errors.New("invalid SFU layer")
}
for _, previous := range value.Layers[:index] {
if previous.RID == layer.RID {
return errors.New("duplicate SFU RID")
}
}
}
return nil
}
func (value *SfuLayer) UnmarshalJSON(data []byte) error {
type raw SfuLayer
present, err := decodeObject(data, (*raw)(value))
if err != nil {
return err
}
return present.require("rid", "width", "height", "bitrate")
}
// SfuSignalMessage travels only on the room's authenticated WebSocket.
type SfuSignalMessage struct {
Type string `json:"type"`
Revision Int `json:"revision"`
PublicationGeneration string `json:"publicationGeneration"`
ConnectionID string `json:"connectionId"`
Kind string `json:"kind"`
Description *SessionDescription `json:"description,omitempty"`
Candidate *IceCandidate `json:"candidate,omitempty"`
Media *SfuMedia `json:"media,omitempty"`
ActiveCount *Int `json:"activeCount,omitempty"`
}
func (SfuSignalMessage) isClientMessage() {}
func (SfuSignalMessage) isServerMessage() {}
func decodeSfuSignal(data []byte) (SfuSignalMessage, error) {
var message SfuSignalMessage
present, err := decodeObject(data, &message)
if err != nil {
return message, err
}
if err := present.require("type", "revision", "publicationGeneration", "connectionId", "kind"); err != nil {
return message, err
}
if err := present.optional("description", "candidate", "media", "activeCount"); err != nil {
return message, err
}
if message.Kind != "layers" && message.ActiveCount != nil {
return message, errors.New("unexpected SFU layer demand")
}
if !validRevision(message.Revision) || !ValidOpaqueID(message.PublicationGeneration) || !ValidOpaqueID(message.ConnectionID) {
return message, errors.New("invalid SFU signal fence")
}
switch message.Kind {
case "layers":
if message.ActiveCount == nil || !inRangeInt(*message.ActiveCount, 0, 3) || message.Description != nil || message.Candidate != nil || message.Media != nil {
return message, errors.New("invalid SFU layer demand")
}
case "media":
if message.Media == nil || message.Description != nil || message.Candidate != nil {
return message, errors.New("invalid SFU media signal")
}
case "subscribe":
if message.Description != nil || message.Candidate != nil || message.Media != nil {
return message, errors.New("invalid SFU subscription signal")
}
case "description":
if message.Description == nil || message.Candidate != nil || message.Media != nil && message.Description.Type != "offer" {
return message, errors.New("invalid SFU description signal")
}
case "candidate":
if message.Description != nil || message.Media != nil {
return message, errors.New("invalid SFU ICE signal")
}
default:
return message, errors.New("unknown SFU signal kind")
}
return message, nil
}