diff --git a/README.md b/README.md index edb76c17..3b2f8c02 100644 --- a/README.md +++ b/README.md @@ -1162,6 +1162,7 @@ Related projects * pion/sdp (SDP library used internally) https://github.com/pion/sdp * pion/rtp (RTP library used internally) https://github.com/pion/rtp * pion/rtcp (RTCP library used internally) https://github.com/pion/rtcp +* pion/webrtc (WebRTC library used internally) https://github.com/pion/webrtc * notedit/rtmp (RTMP library used internally) https://github.com/notedit/rtmp * go-astits (MPEG-TS library used internally) https://github.com/asticode/go-astits * go-mp4 (MP4 library used internally) https://github.com/abema/go-mp4 diff --git a/go.mod b/go.mod index 8313a58b..09fd28c6 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/alecthomas/kong v0.7.1 github.com/aler9/gortsplib/v2 v2.1.4 github.com/asticode/go-astits v1.11.0 - github.com/bluenviron/gohlslib v0.0.0-20230312114838-5feec7e35841 + github.com/bluenviron/gohlslib v0.0.0-20230312151707-933e641d84aa github.com/fsnotify/fsnotify v1.4.9 github.com/gin-gonic/gin v1.9.0 github.com/google/uuid v1.3.0 diff --git a/go.sum b/go.sum index ab8696b4..c2baac0c 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/asticode/go-astikit v0.30.0 h1:DkBkRQRIxYcknlaU7W7ksNfn4gMFsB0tqMJflx github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0= github.com/asticode/go-astits v1.11.0 h1:GTHUXht0ZXAJXsVbsLIcyfHr1Bchi4QQwMARw2ZWAng= github.com/asticode/go-astits v1.11.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI= -github.com/bluenviron/gohlslib v0.0.0-20230312114838-5feec7e35841 h1:J5AIpE6ue/l/IgIlLCi/QQJL2MNBTFQrAkDScGbUaDs= -github.com/bluenviron/gohlslib v0.0.0-20230312114838-5feec7e35841/go.mod h1:SYixOK6Kux6cA9AGR1sg1GJdU2TmYiccVpPmS/Rxdt0= +github.com/bluenviron/gohlslib v0.0.0-20230312151707-933e641d84aa h1:zvGhswcO4E4B9k8+Jx7l+KERoKoQsxGFdMubsf8PVg4= +github.com/bluenviron/gohlslib v0.0.0-20230312151707-933e641d84aa/go.mod h1:SYixOK6Kux6cA9AGR1sg1GJdU2TmYiccVpPmS/Rxdt0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= diff --git a/internal/conf/hlsvariant.go b/internal/conf/hlsvariant.go index 33629ffe..ed9bfcc6 100644 --- a/internal/conf/hlsvariant.go +++ b/internal/conf/hlsvariant.go @@ -8,13 +8,13 @@ import ( ) // HLSVariant is the hlsVariant parameter. -type HLSVariant hls.MuxerVariant +type HLSVariant gohlslib.MuxerVariant // supported HLS variants. const ( - HLSVariantMPEGTS HLSVariant = HLSVariant(hls.MuxerVariantMPEGTS) - HLSVariantFMP4 HLSVariant = HLSVariant(hls.MuxerVariantFMP4) - HLSVariantLowLatency HLSVariant = HLSVariant(hls.MuxerVariantLowLatency) + HLSVariantMPEGTS HLSVariant = HLSVariant(gohlslib.MuxerVariantMPEGTS) + HLSVariantFMP4 HLSVariant = HLSVariant(gohlslib.MuxerVariantFMP4) + HLSVariantLowLatency HLSVariant = HLSVariant(gohlslib.MuxerVariantLowLatency) ) // MarshalJSON implements json.Marshaler. diff --git a/internal/core/hls_muxer.go b/internal/core/hls_muxer.go index d914403a..149cc8f4 100644 --- a/internal/core/hls_muxer.go +++ b/internal/core/hls_muxer.go @@ -36,7 +36,7 @@ var hlsIndex []byte type hlsMuxerResponse struct { muxer *hlsMuxer - cb func() *hls.MuxerFileResponse + cb func() *gohlslib.MuxerFileResponse } type hlsMuxerRequest struct { @@ -77,7 +77,7 @@ type hlsMuxer struct { path *path ringBuffer *ringbuffer.RingBuffer lastRequestTime *int64 - muxer *hls.Muxer + muxer *gohlslib.Muxer requests []*hlsMuxerRequest bytesSent *uint64 @@ -296,17 +296,17 @@ func (m *hlsMuxer) runInner(innerCtx context.Context, innerReady chan struct{}) "the stream doesn't contain any supported codec (which are currently H264, H265, MPEG4-Audio, Opus)") } - var err error - m.muxer, err = hls.NewMuxer( - hls.MuxerVariant(m.variant), - m.segmentCount, - time.Duration(m.segmentDuration), - time.Duration(m.partDuration), - uint64(m.segmentMaxSize), - videoFormat, - audioFormat, - "", - ) + m.muxer = &gohlslib.Muxer{ + Variant: gohlslib.MuxerVariant(m.variant), + SegmentCount: m.segmentCount, + SegmentDuration: time.Duration(m.segmentDuration), + PartDuration: time.Duration(m.partDuration), + SegmentMaxSize: uint64(m.segmentMaxSize), + VideoTrack: videoFormat, + AudioTrack: audioFormat, + } + + err := m.muxer.Start() if err != nil { return fmt.Errorf("muxer error: %v", err) } @@ -507,15 +507,15 @@ func (m *hlsMuxer) runWriter() error { } } -func (m *hlsMuxer) handleRequest(req *hlsMuxerRequest) func() *hls.MuxerFileResponse { +func (m *hlsMuxer) handleRequest(req *hlsMuxerRequest) func() *gohlslib.MuxerFileResponse { atomic.StoreInt64(m.lastRequestTime, time.Now().UnixNano()) err := m.authenticate(req.ctx) if err != nil { if terr, ok := err.(pathErrAuthCritical); ok { m.log(logger.Info, "authentication error: %s", terr.message) - return func() *hls.MuxerFileResponse { - return &hls.MuxerFileResponse{ + return func() *gohlslib.MuxerFileResponse { + return &gohlslib.MuxerFileResponse{ Status: http.StatusUnauthorized, Header: map[string]string{ "WWW-Authenticate": `Basic realm="rtsp-simple-server"`, @@ -524,8 +524,8 @@ func (m *hlsMuxer) handleRequest(req *hlsMuxerRequest) func() *hls.MuxerFileResp } } - return func() *hls.MuxerFileResponse { - return &hls.MuxerFileResponse{ + return func() *gohlslib.MuxerFileResponse { + return &gohlslib.MuxerFileResponse{ Status: http.StatusUnauthorized, Header: map[string]string{ "WWW-Authenticate": `Basic realm="rtsp-simple-server"`, @@ -535,8 +535,8 @@ func (m *hlsMuxer) handleRequest(req *hlsMuxerRequest) func() *hls.MuxerFileResp } if req.file == "" { - return func() *hls.MuxerFileResponse { - return &hls.MuxerFileResponse{ + return func() *gohlslib.MuxerFileResponse { + return &gohlslib.MuxerFileResponse{ Status: http.StatusOK, Header: map[string]string{ "Content-Type": `text/html`, @@ -546,7 +546,7 @@ func (m *hlsMuxer) handleRequest(req *hlsMuxerRequest) func() *hls.MuxerFileResp } } - return func() *hls.MuxerFileResponse { + return func() *gohlslib.MuxerFileResponse { return m.muxer.File( req.file, req.ctx.Query("_HLS_msn"), diff --git a/internal/core/hls_source.go b/internal/core/hls_source.go index d3e296fb..181411f4 100644 --- a/internal/core/hls_source.go +++ b/internal/core/hls_source.go @@ -52,13 +52,10 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan } }() - c, err := hls.NewClient( - cnf.Source, - cnf.SourceFingerprint, - hlsLoggerWrapper(s.Log), - ) - if err != nil { - return err + c := &gohlslib.Client{ + URI: cnf.Source, + Fingerprint: cnf.SourceFingerprint, + Logger: hlsLoggerWrapper(s.Log), } c.OnTracks(func(tracks []format.Format) error { @@ -144,11 +141,15 @@ func (s *hlsSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan return nil }) - c.Start() + err := c.Start() + if err != nil { + return err + } for { select { case err := <-c.Wait(): + c.Close() return err case <-reloadConf: diff --git a/internal/core/webrtc_server_test.go b/internal/core/webrtc_server_test.go index 5be0de60..bc9e59d2 100644 --- a/internal/core/webrtc_server_test.go +++ b/internal/core/webrtc_server_test.go @@ -2,6 +2,7 @@ package core import ( "encoding/json" + "sync" "testing" "time" @@ -58,18 +59,23 @@ func newWebRTCTestClient(addr string) (*webRTCTestClient, error) { connected := make(chan struct{}) closed := make(chan struct{}) + var stateChangeMutex sync.Mutex pc.OnConnectionStateChange(func(state webrtc.PeerConnectionState) { + stateChangeMutex.Lock() + defer stateChangeMutex.Unlock() + + select { + case <-closed: + return + default: + } + switch state { case webrtc.PeerConnectionStateConnected: close(connected) case webrtc.PeerConnectionStateClosed: - select { - case <-closed: - return - default: - } close(closed) } })