bluenviron / gortsplib

RTSP 1.0 client and server library for the Go programming language
MIT License
636 stars 177 forks source link

Could you please tell me how to make SPS and PPS not in the same rtp package when rtsp is pushing the stream #534

Closed Linsugar closed 2 months ago

Linsugar commented 3 months ago

package main

import ( "fmt" "log" "sync"

"github.com/pion/rtp"

"github.com/bluenviron/gortsplib/v4"
"github.com/bluenviron/gortsplib/v4/pkg/base"
"github.com/bluenviron/gortsplib/v4/pkg/description"
"github.com/bluenviron/gortsplib/v4/pkg/format"

)

type serverHandler struct { s gortsplib.Server mutex sync.Mutex stream gortsplib.ServerStream publisher *gortsplib.ServerSession }

// OnConnOpen xxx . func (sh serverHandler) OnConnOpen(ctx gortsplib.ServerHandlerOnConnOpenCtx) { log.Printf("xxx ") }

// OnConnClose xx. func (sh serverHandler) OnConnClose(ctx gortsplib.ServerHandlerOnConnCloseCtx) { log.Printf("(%v)", ctx.Error) }

// OnSessionOpen xx. func (sh serverHandler) OnSessionOpen(ctx gortsplib.ServerHandlerOnSessionOpenCtx) { log.Printf("xx") }

// OnSessionClose xx. func (sh serverHandler) OnSessionClose(ctx gortsplib.ServerHandlerOnSessionCloseCtx) { log.Printf("xx")

sh.mutex.Lock()
defer sh.mutex.Unlock()

// if the session is the publisher,
// close the stream and disconnect any reader.
if sh.stream != nil && ctx.Session == sh.publisher {
    sh.stream.Close()
    sh.stream = nil
}

}

// OnDescribe xx. func (sh serverHandler) OnDescribe(ctx gortsplib.ServerHandlerOnDescribeCtx) (base.Response, gortsplib.ServerStream, error) { log.Printf("xx") sh.mutex.Lock() defer sh.mutex.Unlock()

if sh.stream == nil {
    return &base.Response{
        StatusCode: base.StatusNotFound,
    }, nil, nil
}

return &base.Response{
    StatusCode: base.StatusOK,
}, sh.stream, nil

}

// OnAnnounce called when receiving an ANNOUNCE request. func (sh serverHandler) OnAnnounce(ctx gortsplib.ServerHandlerOnAnnounceCtx) (base.Response, error) { sh.mutex.Lock() log.Printf("announce request") var forma format.H264 _ = ctx.Description.FindFormat(&forma)

defer sh.mutex.Unlock()

// disconnect existing publisher
if sh.stream != nil {
    sh.stream.Close()
    sh.publisher.Close()
}
// create the stream and save the publisher
sh.stream = gortsplib.NewServerStream(sh.s, ctx.Description)
sh.publisher = ctx.Session

return &base.Response{
    StatusCode: base.StatusOK,
}, nil

}

// OnSetup called when receiving a SETUP request. func (sh serverHandler) OnSetup(ctx gortsplib.ServerHandlerOnSetupCtx) (base.Response, gortsplib.ServerStream, error) { log.Printf("setup request")

// no one is publishing yet
if sh.stream == nil {
    return &base.Response{
        StatusCode: base.StatusNotFound,
    }, nil, nil
}

return &base.Response{
    StatusCode: base.StatusOK,
}, sh.stream, nil

}

// OnPlay called when receiving a PLAY request. func (sh serverHandler) OnPlay(ctx gortsplib.ServerHandlerOnPlayCtx) (*base.Response, error) { log.Printf("xx")

return &base.Response{
    StatusCode: base.StatusOK,
}, nil

}

// OnRecord called when receiving a RECORD request. func (sh serverHandler) OnRecord(ctx gortsplib.ServerHandlerOnRecordCtx) (*base.Response, error) { log.Printf("xxx")

// called when receiving an RTP packet
ctx.Session.OnPacketRTPAny(func(medi *description.Media, forma format.Format, pkt *rtp.Packet) {

    // route the RTP packet to all readers
    err := sh.stream.WritePacketRTP(medi, pkt)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
})

return &base.Response{
    StatusCode: base.StatusOK,
}, nil

}

func main() { // configure the server

h := &serverHandler{}
h.s = &gortsplib.Server{
    Handler:           h,
    RTSPAddress:       ":8554",
    UDPRTPAddress:     ":8000",
    UDPRTCPAddress:    ":8001",
    MulticastIPRange:  "224.1.0.0/16",
    MulticastRTPPort:  8002,
    MulticastRTCPPort: 8003,
}

// start server and wait until a fatal error
log.Printf("xx:xx(%d)", 8554)
panic(h.s.StartAndWait())

}

aler9 commented 2 months ago

Hello, SPS and PPS are wrapped inside RTP packets by the client, not by the server. The server just routes RTP packets from a client (publisher) to other clients (readers), without touching them.

Putting SPS and PPS in the same RTP packet is performed by the great majority of publishers to save bandwidth, therefore, if you need to extract them, you'd better just decode incoming RTP packets by using the CreateDecoder() method, like in this example:

https://github.com/bluenviron/gortsplib/blob/main/examples/server-h264-save-to-disk/main.go