bluenviron / gortsplib

RTSP 1.0 client and server library for the Go programming language

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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