Could you please tell me how to make SPS and PPS not in the same rtp package when rtsp is pushing the stream
Linsugar opened this issue · comments
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())
}
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