rtsp: add rtspScale parameter to inject Scale header on PLAY (#5800)
Co-authored-by: aler9 <46489434+aler9@users.noreply.github.com>
This commit is contained in:
@@ -782,6 +782,8 @@ components:
|
|||||||
$ref: "#/components/schemas/RTSPRangeType"
|
$ref: "#/components/schemas/RTSPRangeType"
|
||||||
rtspRangeStart:
|
rtspRangeStart:
|
||||||
type: string
|
type: string
|
||||||
|
rtspScale:
|
||||||
|
type: string
|
||||||
rtspUDPReadBufferSize:
|
rtspUDPReadBufferSize:
|
||||||
type: integer
|
type: integer
|
||||||
format: uint64
|
format: uint64
|
||||||
|
|||||||
@@ -257,6 +257,7 @@ type Path struct {
|
|||||||
SourceAnyPortEnable *bool `json:"sourceAnyPortEnable,omitempty" deprecated:"true"`
|
SourceAnyPortEnable *bool `json:"sourceAnyPortEnable,omitempty" deprecated:"true"`
|
||||||
RTSPRangeType RTSPRangeType `json:"rtspRangeType"`
|
RTSPRangeType RTSPRangeType `json:"rtspRangeType"`
|
||||||
RTSPRangeStart string `json:"rtspRangeStart"`
|
RTSPRangeStart string `json:"rtspRangeStart"`
|
||||||
|
RTSPScale string `json:"rtspScale"`
|
||||||
RTSPUDPReadBufferSize *uint `json:"rtspUDPReadBufferSize,omitempty" deprecated:"true"`
|
RTSPUDPReadBufferSize *uint `json:"rtspUDPReadBufferSize,omitempty" deprecated:"true"`
|
||||||
RTSPUDPSourcePortRange []uint `json:"rtspUDPSourcePortRange"`
|
RTSPUDPSourcePortRange []uint `json:"rtspUDPSourcePortRange"`
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,12 @@ func (s *Source) Run(params defs.StaticSourceRunParams) error {
|
|||||||
uint16(params.Conf.RTSPUDPSourcePortRange[1]),
|
uint16(params.Conf.RTSPUDPSourcePortRange[1]),
|
||||||
},
|
},
|
||||||
OnRequest: func(req *base.Request) {
|
OnRequest: func(req *base.Request) {
|
||||||
|
if params.Conf.RTSPScale != "" && req.Method == base.Play {
|
||||||
|
if req.Header == nil {
|
||||||
|
req.Header = base.Header{}
|
||||||
|
}
|
||||||
|
req.Header["Scale"] = base.HeaderValue{params.Conf.RTSPScale}
|
||||||
|
}
|
||||||
s.Log(logger.Debug, "[c->s] %v", req)
|
s.Log(logger.Debug, "[c->s] %v", req)
|
||||||
},
|
},
|
||||||
OnResponse: func(res *base.Response) {
|
OnResponse: func(res *base.Response) {
|
||||||
|
|||||||
@@ -305,6 +305,96 @@ func TestNoPassword(t *testing.T) {
|
|||||||
<-p.Unit
|
<-p.Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestScale(t *testing.T) {
|
||||||
|
var strm *gortsplib.ServerStream
|
||||||
|
|
||||||
|
media0 := test.UniqueMediaH264()
|
||||||
|
|
||||||
|
s := gortsplib.Server{
|
||||||
|
Handler: &testServer{
|
||||||
|
onDescribe: func(_ *gortsplib.ServerHandlerOnDescribeCtx) (*base.Response, *gortsplib.ServerStream, error) {
|
||||||
|
return &base.Response{
|
||||||
|
StatusCode: base.StatusOK,
|
||||||
|
}, strm, nil
|
||||||
|
},
|
||||||
|
onSetup: func(_ *gortsplib.ServerHandlerOnSetupCtx) (*base.Response, *gortsplib.ServerStream, error) {
|
||||||
|
return &base.Response{
|
||||||
|
StatusCode: base.StatusOK,
|
||||||
|
}, strm, nil
|
||||||
|
},
|
||||||
|
onPlay: func(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Response, error) {
|
||||||
|
require.Equal(t, base.HeaderValue{"-1.0"}, ctx.Request.Header["Scale"])
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
err := strm.WritePacketRTP(media0, &rtp.Packet{
|
||||||
|
Header: rtp.Header{
|
||||||
|
Version: 0x02,
|
||||||
|
PayloadType: 96,
|
||||||
|
SequenceNumber: 57899,
|
||||||
|
Timestamp: 345234345,
|
||||||
|
SSRC: 978651231,
|
||||||
|
Marker: true,
|
||||||
|
},
|
||||||
|
Payload: []byte{5, 1, 2, 3, 4},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return &base.Response{
|
||||||
|
StatusCode: base.StatusOK,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RTSPAddress: "127.0.0.1:8555",
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.Start()
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
strm = &gortsplib.ServerStream{
|
||||||
|
Server: &s,
|
||||||
|
Desc: &description.Session{Medias: []*description.Media{media0}},
|
||||||
|
}
|
||||||
|
err = strm.Initialize()
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer strm.Close()
|
||||||
|
|
||||||
|
cnf := &conf.Path{
|
||||||
|
RTSPUDPSourcePortRange: []uint{10000, 65535},
|
||||||
|
RTSPScale: "-1.0",
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &test.StaticSourceParent{}
|
||||||
|
p.Initialize()
|
||||||
|
defer p.Close()
|
||||||
|
|
||||||
|
so := &Source{
|
||||||
|
ReadTimeout: conf.Duration(10 * time.Second),
|
||||||
|
WriteTimeout: conf.Duration(10 * time.Second),
|
||||||
|
WriteQueueSize: 2048,
|
||||||
|
Parent: p,
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
defer func() { <-done }()
|
||||||
|
|
||||||
|
ctx, ctxCancel := context.WithCancel(context.Background())
|
||||||
|
defer ctxCancel()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
so.Run(defs.StaticSourceRunParams{ //nolint:errcheck
|
||||||
|
Context: ctx,
|
||||||
|
ResolvedSource: "rtsp://127.0.0.1:8555/teststream",
|
||||||
|
Conf: cnf,
|
||||||
|
})
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-p.Unit
|
||||||
|
}
|
||||||
|
|
||||||
func TestRange(t *testing.T) {
|
func TestRange(t *testing.T) {
|
||||||
for _, ca := range []string{"clock", "npt", "smpte"} {
|
for _, ca := range []string{"clock", "npt", "smpte"} {
|
||||||
t.Run(ca, func(t *testing.T) {
|
t.Run(ca, func(t *testing.T) {
|
||||||
|
|||||||
@@ -593,6 +593,10 @@ pathDefaults:
|
|||||||
# * npt: duration such as "300ms", "1.5m" or "2h45m", valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"
|
# * npt: duration such as "300ms", "1.5m" or "2h45m", valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"
|
||||||
# * smpte: duration such as "300ms", "1.5m" or "2h45m", valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"
|
# * smpte: duration such as "300ms", "1.5m" or "2h45m", valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h"
|
||||||
rtspRangeStart:
|
rtspRangeStart:
|
||||||
|
# Scale header value to send to the source, in order to play the stream at a different speed.
|
||||||
|
# Negative values play in reverse, values > 1 fast-forward,
|
||||||
|
# values 0 < x < 1 play slow motion.
|
||||||
|
rtspScale:
|
||||||
# Range of ports used as source port in outgoing UDP packets.
|
# Range of ports used as source port in outgoing UDP packets.
|
||||||
rtspUDPSourcePortRange: [10000, 65535]
|
rtspUDPSourcePortRange: [10000, 65535]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user