From a9e7a73cc8e0a25d21226f00f606703feb83b932 Mon Sep 17 00:00:00 2001 From: Alex X Date: Tue, 28 May 2024 14:01:42 +0300 Subject: [PATCH] Add video bitrate setting for HomeKit source --- internal/homekit/homekit.go | 32 ++++++++++++++++++++++++++++++-- pkg/hap/camera/stream.go | 13 ++++++++++--- pkg/homekit/client.go | 4 +++- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/internal/homekit/homekit.go b/internal/homekit/homekit.go index bfe3e971..743aeab9 100644 --- a/internal/homekit/homekit.go +++ b/internal/homekit/homekit.go @@ -133,12 +133,19 @@ func Init() { var log zerolog.Logger var servers map[string]*server -func streamHandler(url string) (core.Producer, error) { +func streamHandler(rawURL string) (core.Producer, error) { if srtp.Server == nil { return nil, errors.New("homekit: can't work without SRTP server") } - return homekit.Dial(url, srtp.Server) + rawURL, rawQuery, _ := strings.Cut(rawURL, "#") + client, err := homekit.Dial(rawURL, srtp.Server) + if client != nil && rawQuery != "" { + query := streams.ParseQuery(rawQuery) + client.Bitrate = parseBitrate(query.Get("bitrate")) + } + + return client, err } func hapPairSetup(w http.ResponseWriter, r *http.Request) { @@ -199,3 +206,24 @@ func findHomeKitURL(stream *streams.Stream) string { return "" } + +func parseBitrate(s string) int { + n := len(s) + if n == 0 { + return 0 + } + + var k int + switch n--; s[n] { + case 'K': + k = 1024 + s = s[:n] + case 'M': + k = 1024 * 1024 + s = s[:n] + default: + k = 1 + } + + return k * core.Atoi(s) +} diff --git a/pkg/hap/camera/stream.go b/pkg/hap/camera/stream.go index b2ef0d9f..23d53c39 100644 --- a/pkg/hap/camera/stream.go +++ b/pkg/hap/camera/stream.go @@ -15,7 +15,8 @@ type Stream struct { } func NewStream( - client *hap.Client, videoCodec *VideoCodec, audioCodec *AudioCodec, videoSession, audioSession *srtp.Session, + client *hap.Client, videoCodec *VideoCodec, audioCodec *AudioCodec, + videoSession, audioSession *srtp.Session, bitrate int, ) (*Stream, error) { stream := &Stream{ id: core.RandString(16, 0), @@ -30,11 +31,17 @@ func NewStream( return nil, err } + if bitrate != 0 { + bitrate /= 1024 // convert bps to kbps + } else { + bitrate = 4096 // default kbps for general FullHD camera + } + videoCodec.RTPParams = []RTPParams{ { PayloadType: 99, SSRC: videoSession.Local.SSRC, - MaxBitrate: 299, + MaxBitrate: uint16(bitrate), // iPhone query 299Kbps, iPad/AppleTV query 802Kbps RTCPInterval: 0.5, MaxMTU: []uint16{1378}, }, @@ -43,7 +50,7 @@ func NewStream( { PayloadType: 110, SSRC: audioSession.Local.SSRC, - MaxBitrate: 24, + MaxBitrate: 24, // any iDevice query 24Kbps (this is OK for 16KHz and 1 channel) RTCPInterval: 5, ComfortNoisePayloadType: []uint8{13}, diff --git a/pkg/homekit/client.go b/pkg/homekit/client.go index c61acea6..133499d3 100644 --- a/pkg/homekit/client.go +++ b/pkg/homekit/client.go @@ -28,6 +28,8 @@ type Client struct { audioSession *srtp.Session stream *camera.Stream + + Bitrate int // in bits/s } func Dial(rawURL string, server *srtp.Server) (*Client, error) { @@ -132,7 +134,7 @@ func (c *Client) Start() error { c.audioSession = &srtp.Session{Local: c.srtpEndpoint()} var err error - c.stream, err = camera.NewStream(c.hap, videoCodec, audioCodec, c.videoSession, c.audioSession) + c.stream, err = camera.NewStream(c.hap, videoCodec, audioCodec, c.videoSession, c.audioSession, c.Bitrate) if err != nil { return err }