mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-10-26 09:10:27 +08:00
add option to set max size of outgoing UDP packets (#1588) (#1601)
Some checks failed
apidocs
code
mod-tidy
test32
test64
test_highlevel
Some checks failed
apidocs
code
mod-tidy
test32
test64
test_highlevel
This commit is contained in:
@@ -33,6 +33,8 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
readBufferCount:
|
readBufferCount:
|
||||||
type: integer
|
type: integer
|
||||||
|
udpMaxPayloadSize:
|
||||||
|
type: integer
|
||||||
externalAuthenticationURL:
|
externalAuthenticationURL:
|
||||||
type: string
|
type: string
|
||||||
api:
|
api:
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ type Conf struct {
|
|||||||
ReadTimeout StringDuration `json:"readTimeout"`
|
ReadTimeout StringDuration `json:"readTimeout"`
|
||||||
WriteTimeout StringDuration `json:"writeTimeout"`
|
WriteTimeout StringDuration `json:"writeTimeout"`
|
||||||
ReadBufferCount int `json:"readBufferCount"`
|
ReadBufferCount int `json:"readBufferCount"`
|
||||||
|
UDPMaxPayloadSize int `json:"udpMaxPayloadSize"`
|
||||||
ExternalAuthenticationURL string `json:"externalAuthenticationURL"`
|
ExternalAuthenticationURL string `json:"externalAuthenticationURL"`
|
||||||
API bool `json:"api"`
|
API bool `json:"api"`
|
||||||
APIAddress string `json:"apiAddress"`
|
APIAddress string `json:"apiAddress"`
|
||||||
@@ -285,7 +286,13 @@ func (conf *Conf) CheckAndFillMissing() error {
|
|||||||
conf.ReadBufferCount = 512
|
conf.ReadBufferCount = 512
|
||||||
}
|
}
|
||||||
if (conf.ReadBufferCount & (conf.ReadBufferCount - 1)) != 0 {
|
if (conf.ReadBufferCount & (conf.ReadBufferCount - 1)) != 0 {
|
||||||
return fmt.Errorf("'ReadBufferCount' must be a power of two")
|
return fmt.Errorf("'readBufferCount' must be a power of two")
|
||||||
|
}
|
||||||
|
if conf.UDPMaxPayloadSize == 0 {
|
||||||
|
conf.UDPMaxPayloadSize = 1500
|
||||||
|
}
|
||||||
|
if conf.UDPMaxPayloadSize > 1500 {
|
||||||
|
return fmt.Errorf("'udpMaxPayloadSize' must be less than 1500")
|
||||||
}
|
}
|
||||||
if conf.ExternalAuthenticationURL != "" {
|
if conf.ExternalAuthenticationURL != "" {
|
||||||
if !strings.HasPrefix(conf.ExternalAuthenticationURL, "http://") &&
|
if !strings.HasPrefix(conf.ExternalAuthenticationURL, "http://") &&
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ func (p *Core) createResources(initial bool) error {
|
|||||||
p.conf.ReadTimeout,
|
p.conf.ReadTimeout,
|
||||||
p.conf.WriteTimeout,
|
p.conf.WriteTimeout,
|
||||||
p.conf.ReadBufferCount,
|
p.conf.ReadBufferCount,
|
||||||
|
p.conf.UDPMaxPayloadSize,
|
||||||
p.conf.Paths,
|
p.conf.Paths,
|
||||||
p.externalCmdPool,
|
p.externalCmdPool,
|
||||||
p.metrics,
|
p.metrics,
|
||||||
@@ -486,6 +487,7 @@ func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
|
|||||||
newConf.ReadTimeout != p.conf.ReadTimeout ||
|
newConf.ReadTimeout != p.conf.ReadTimeout ||
|
||||||
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
newConf.WriteTimeout != p.conf.WriteTimeout ||
|
||||||
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
newConf.ReadBufferCount != p.conf.ReadBufferCount ||
|
||||||
|
newConf.UDPMaxPayloadSize != p.conf.UDPMaxPayloadSize ||
|
||||||
closeMetrics
|
closeMetrics
|
||||||
if !closePathManager && !reflect.DeepEqual(newConf.Paths, p.conf.Paths) {
|
if !closePathManager && !reflect.DeepEqual(newConf.Paths, p.conf.Paths) {
|
||||||
p.pathManager.confReload(newConf.Paths)
|
p.pathManager.confReload(newConf.Paths)
|
||||||
|
|||||||
@@ -187,17 +187,18 @@ type pathAPIPathsListSubReq struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type path struct {
|
type path struct {
|
||||||
rtspAddress string
|
rtspAddress string
|
||||||
readTimeout conf.StringDuration
|
readTimeout conf.StringDuration
|
||||||
writeTimeout conf.StringDuration
|
writeTimeout conf.StringDuration
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
confName string
|
udpMaxPayloadSize int
|
||||||
conf *conf.PathConf
|
confName string
|
||||||
name string
|
conf *conf.PathConf
|
||||||
matches []string
|
name string
|
||||||
wg *sync.WaitGroup
|
matches []string
|
||||||
externalCmdPool *externalcmd.Pool
|
wg *sync.WaitGroup
|
||||||
parent pathParent
|
externalCmdPool *externalcmd.Pool
|
||||||
|
parent pathParent
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
ctxCancel func()
|
ctxCancel func()
|
||||||
@@ -240,6 +241,7 @@ func newPath(
|
|||||||
readTimeout conf.StringDuration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout conf.StringDuration,
|
writeTimeout conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
|
udpMaxPayloadSize int,
|
||||||
confName string,
|
confName string,
|
||||||
cnf *conf.PathConf,
|
cnf *conf.PathConf,
|
||||||
name string,
|
name string,
|
||||||
@@ -255,6 +257,7 @@ func newPath(
|
|||||||
readTimeout: readTimeout,
|
readTimeout: readTimeout,
|
||||||
writeTimeout: writeTimeout,
|
writeTimeout: writeTimeout,
|
||||||
readBufferCount: readBufferCount,
|
readBufferCount: readBufferCount,
|
||||||
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
confName: confName,
|
confName: confName,
|
||||||
conf: cnf,
|
conf: cnf,
|
||||||
name: name,
|
name: name,
|
||||||
@@ -632,7 +635,12 @@ func (pa *path) onDemandPublisherStop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pa *path) sourceSetReady(medias media.Medias, allocateEncoder bool) error {
|
func (pa *path) sourceSetReady(medias media.Medias, allocateEncoder bool) error {
|
||||||
stream, err := newStream(medias, allocateEncoder, pa.bytesReceived)
|
stream, err := newStream(
|
||||||
|
pa.udpMaxPayloadSize,
|
||||||
|
medias,
|
||||||
|
allocateEncoder,
|
||||||
|
pa.bytesReceived,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,14 +40,15 @@ type pathManagerParent interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type pathManager struct {
|
type pathManager struct {
|
||||||
rtspAddress string
|
rtspAddress string
|
||||||
readTimeout conf.StringDuration
|
readTimeout conf.StringDuration
|
||||||
writeTimeout conf.StringDuration
|
writeTimeout conf.StringDuration
|
||||||
readBufferCount int
|
readBufferCount int
|
||||||
pathConfs map[string]*conf.PathConf
|
udpMaxPayloadSize int
|
||||||
externalCmdPool *externalcmd.Pool
|
pathConfs map[string]*conf.PathConf
|
||||||
metrics *metrics
|
externalCmdPool *externalcmd.Pool
|
||||||
parent pathManagerParent
|
metrics *metrics
|
||||||
|
parent pathManagerParent
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
ctxCancel func()
|
ctxCancel func()
|
||||||
@@ -74,6 +75,7 @@ func newPathManager(
|
|||||||
readTimeout conf.StringDuration,
|
readTimeout conf.StringDuration,
|
||||||
writeTimeout conf.StringDuration,
|
writeTimeout conf.StringDuration,
|
||||||
readBufferCount int,
|
readBufferCount int,
|
||||||
|
udpMaxPayloadSize int,
|
||||||
pathConfs map[string]*conf.PathConf,
|
pathConfs map[string]*conf.PathConf,
|
||||||
externalCmdPool *externalcmd.Pool,
|
externalCmdPool *externalcmd.Pool,
|
||||||
metrics *metrics,
|
metrics *metrics,
|
||||||
@@ -86,6 +88,7 @@ func newPathManager(
|
|||||||
readTimeout: readTimeout,
|
readTimeout: readTimeout,
|
||||||
writeTimeout: writeTimeout,
|
writeTimeout: writeTimeout,
|
||||||
readBufferCount: readBufferCount,
|
readBufferCount: readBufferCount,
|
||||||
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
pathConfs: pathConfs,
|
pathConfs: pathConfs,
|
||||||
externalCmdPool: externalCmdPool,
|
externalCmdPool: externalCmdPool,
|
||||||
metrics: metrics,
|
metrics: metrics,
|
||||||
@@ -303,6 +306,7 @@ func (pm *pathManager) createPath(
|
|||||||
pm.readTimeout,
|
pm.readTimeout,
|
||||||
pm.writeTimeout,
|
pm.writeTimeout,
|
||||||
pm.readBufferCount,
|
pm.readBufferCount,
|
||||||
|
pm.udpMaxPayloadSize,
|
||||||
pathConfName,
|
pathConfName,
|
||||||
pathConf,
|
pathConf,
|
||||||
name,
|
name,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ type stream struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newStream(
|
func newStream(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
medias media.Medias,
|
medias media.Medias,
|
||||||
generateRTPPackets bool,
|
generateRTPPackets bool,
|
||||||
bytesReceived *uint64,
|
bytesReceived *uint64,
|
||||||
@@ -28,7 +29,7 @@ func newStream(
|
|||||||
|
|
||||||
for _, media := range s.rtspStream.Medias() {
|
for _, media := range s.rtspStream.Medias() {
|
||||||
var err error
|
var err error
|
||||||
s.smedias[media], err = newStreamMedia(media, generateRTPPackets)
|
s.smedias[media], err = newStreamMedia(udpMaxPayloadSize, media, generateRTPPackets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,12 @@ type streamFormat struct {
|
|||||||
nonRTSPReaders map[reader]func(formatprocessor.Unit)
|
nonRTSPReaders map[reader]func(formatprocessor.Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStreamFormat(forma format.Format, generateRTPPackets bool) (*streamFormat, error) {
|
func newStreamFormat(
|
||||||
proc, err := formatprocessor.New(forma, generateRTPPackets)
|
udpMaxPayloadSize int,
|
||||||
|
forma format.Format,
|
||||||
|
generateRTPPackets bool,
|
||||||
|
) (*streamFormat, error) {
|
||||||
|
proc, err := formatprocessor.New(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,17 @@ type streamMedia struct {
|
|||||||
formats map[format.Format]*streamFormat
|
formats map[format.Format]*streamFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStreamMedia(medi *media.Media, generateRTPPackets bool) (*streamMedia, error) {
|
func newStreamMedia(udpMaxPayloadSize int,
|
||||||
|
medi *media.Media,
|
||||||
|
generateRTPPackets bool,
|
||||||
|
) (*streamMedia, error) {
|
||||||
sm := &streamMedia{
|
sm := &streamMedia{
|
||||||
formats: make(map[format.Format]*streamFormat),
|
formats: make(map[format.Format]*streamFormat),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, forma := range medi.Formats {
|
for _, forma := range medi.Formats {
|
||||||
var err error
|
var err error
|
||||||
sm.formats[forma], err = newStreamFormat(forma, generateRTPPackets)
|
sm.formats[forma], err = newStreamFormat(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
multicastTTL = 16
|
multicastTTL = 16
|
||||||
|
udpMTU = 1472
|
||||||
)
|
)
|
||||||
|
|
||||||
var opusDurations = [32]int{
|
var opusDurations = [32]int{
|
||||||
@@ -127,7 +128,7 @@ func (s *udpSource) run(ctx context.Context, cnf *conf.PathConf, reloadConf chan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
midbuffer := make([]byte, 0, 1472) // UDP MTU
|
midbuffer := make([]byte, 0, udpMTU)
|
||||||
midbufferPos := 0
|
midbufferPos := 0
|
||||||
|
|
||||||
readPacket := func(buf []byte) (int, error) {
|
readPacket := func(buf []byte) (int, error) {
|
||||||
|
|||||||
@@ -8,11 +8,6 @@ import (
|
|||||||
"github.com/pion/rtp"
|
"github.com/pion/rtp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
// 1500 (UDP MTU) - 20 (IP header) - 8 (UDP header)
|
|
||||||
maxPacketSize = 1472
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnitGeneric is a generic data unit.
|
// UnitGeneric is a generic data unit.
|
||||||
type UnitGeneric struct {
|
type UnitGeneric struct {
|
||||||
RTPPackets []*rtp.Packet
|
RTPPackets []*rtp.Packet
|
||||||
@@ -29,14 +24,22 @@ func (d *UnitGeneric) GetNTP() time.Time {
|
|||||||
return d.NTP
|
return d.NTP
|
||||||
}
|
}
|
||||||
|
|
||||||
type formatProcessorGeneric struct{}
|
type formatProcessorGeneric struct {
|
||||||
|
udpMaxPayloadSize int
|
||||||
|
}
|
||||||
|
|
||||||
func newGeneric(forma format.Format, generateRTPPackets bool) (*formatProcessorGeneric, error) {
|
func newGeneric(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
|
forma format.Format,
|
||||||
|
generateRTPPackets bool,
|
||||||
|
) (*formatProcessorGeneric, error) {
|
||||||
if generateRTPPackets {
|
if generateRTPPackets {
|
||||||
return nil, fmt.Errorf("we don't know how to generate RTP packets of format %+v", forma)
|
return nil, fmt.Errorf("we don't know how to generate RTP packets of format %+v", forma)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &formatProcessorGeneric{}, nil
|
return &formatProcessorGeneric{
|
||||||
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *formatProcessorGeneric) Process(unit Unit, hasNonRTSPReaders bool) error {
|
func (t *formatProcessorGeneric) Process(unit Unit, hasNonRTSPReaders bool) error {
|
||||||
@@ -48,9 +51,9 @@ func (t *formatProcessorGeneric) Process(unit Unit, hasNonRTSPReaders bool) erro
|
|||||||
pkt.Header.Padding = false
|
pkt.Header.Padding = false
|
||||||
pkt.PaddingSize = 0
|
pkt.PaddingSize = 0
|
||||||
|
|
||||||
if pkt.MarshalSize() > maxPacketSize {
|
if pkt.MarshalSize() > t.udpMaxPayloadSize {
|
||||||
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
||||||
pkt.MarshalSize(), maxPacketSize)
|
pkt.MarshalSize(), t.udpMaxPayloadSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func TestGenericRemovePadding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
forma.Init()
|
forma.Init()
|
||||||
|
|
||||||
p, err := New(forma, false)
|
p, err := New(1472, forma, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pkt := &rtp.Packet{
|
pkt := &rtp.Packet{
|
||||||
|
|||||||
@@ -86,18 +86,21 @@ func (d *UnitH264) GetNTP() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type formatProcessorH264 struct {
|
type formatProcessorH264 struct {
|
||||||
format *format.H264
|
udpMaxPayloadSize int
|
||||||
|
format *format.H264
|
||||||
|
|
||||||
encoder *rtph264.Encoder
|
encoder *rtph264.Encoder
|
||||||
decoder *rtph264.Decoder
|
decoder *rtph264.Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newH264(
|
func newH264(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
forma *format.H264,
|
forma *format.H264,
|
||||||
allocateEncoder bool,
|
allocateEncoder bool,
|
||||||
) (*formatProcessorH264, error) {
|
) (*formatProcessorH264, error) {
|
||||||
t := &formatProcessorH264{
|
t := &formatProcessorH264{
|
||||||
format: forma,
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
|
format: forma,
|
||||||
}
|
}
|
||||||
|
|
||||||
if allocateEncoder {
|
if allocateEncoder {
|
||||||
@@ -211,11 +214,12 @@ func (t *formatProcessorH264) Process(unit Unit, hasNonRTSPReaders bool) error {
|
|||||||
pkt.PaddingSize = 0
|
pkt.PaddingSize = 0
|
||||||
|
|
||||||
// RTP packets exceed maximum size: start re-encoding them
|
// RTP packets exceed maximum size: start re-encoding them
|
||||||
if pkt.MarshalSize() > maxPacketSize {
|
if pkt.MarshalSize() > t.udpMaxPayloadSize {
|
||||||
v1 := pkt.SSRC
|
v1 := pkt.SSRC
|
||||||
v2 := pkt.SequenceNumber
|
v2 := pkt.SequenceNumber
|
||||||
v3 := pkt.Timestamp
|
v3 := pkt.Timestamp
|
||||||
t.encoder = &rtph264.Encoder{
|
t.encoder = &rtph264.Encoder{
|
||||||
|
PayloadMaxSize: t.udpMaxPayloadSize - 12,
|
||||||
PayloadType: pkt.PayloadType,
|
PayloadType: pkt.PayloadType,
|
||||||
SSRC: &v1,
|
SSRC: &v1,
|
||||||
InitialSequenceNumber: &v2,
|
InitialSequenceNumber: &v2,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func TestH264DynamicParams(t *testing.T) {
|
|||||||
PacketizationMode: 1,
|
PacketizationMode: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := New(forma, false)
|
p, err := New(1472, forma, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
enc := forma.CreateEncoder()
|
enc := forma.CreateEncoder()
|
||||||
@@ -61,7 +61,7 @@ func TestH264OversizedPackets(t *testing.T) {
|
|||||||
PacketizationMode: 1,
|
PacketizationMode: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := New(forma, false)
|
p, err := New(1472, forma, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var out []*rtp.Packet
|
var out []*rtp.Packet
|
||||||
@@ -158,7 +158,7 @@ func TestH264EmptyPacket(t *testing.T) {
|
|||||||
PacketizationMode: 1,
|
PacketizationMode: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := New(forma, true)
|
p, err := New(1472, forma, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
unit := &UnitH264{
|
unit := &UnitH264{
|
||||||
|
|||||||
@@ -93,18 +93,21 @@ func (d *UnitH265) GetNTP() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type formatProcessorH265 struct {
|
type formatProcessorH265 struct {
|
||||||
format *format.H265
|
udpMaxPayloadSize int
|
||||||
|
format *format.H265
|
||||||
|
|
||||||
encoder *rtph265.Encoder
|
encoder *rtph265.Encoder
|
||||||
decoder *rtph265.Decoder
|
decoder *rtph265.Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newH265(
|
func newH265(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
forma *format.H265,
|
forma *format.H265,
|
||||||
allocateEncoder bool,
|
allocateEncoder bool,
|
||||||
) (*formatProcessorH265, error) {
|
) (*formatProcessorH265, error) {
|
||||||
t := &formatProcessorH265{
|
t := &formatProcessorH265{
|
||||||
format: forma,
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
|
format: forma,
|
||||||
}
|
}
|
||||||
|
|
||||||
if allocateEncoder {
|
if allocateEncoder {
|
||||||
@@ -232,11 +235,12 @@ func (t *formatProcessorH265) Process(unit Unit, hasNonRTSPReaders bool) error {
|
|||||||
pkt.PaddingSize = 0
|
pkt.PaddingSize = 0
|
||||||
|
|
||||||
// RTP packets exceed maximum size: start re-encoding them
|
// RTP packets exceed maximum size: start re-encoding them
|
||||||
if pkt.MarshalSize() > maxPacketSize {
|
if pkt.MarshalSize() > t.udpMaxPayloadSize {
|
||||||
v1 := pkt.SSRC
|
v1 := pkt.SSRC
|
||||||
v2 := pkt.SequenceNumber
|
v2 := pkt.SequenceNumber
|
||||||
v3 := pkt.Timestamp
|
v3 := pkt.Timestamp
|
||||||
t.encoder = &rtph265.Encoder{
|
t.encoder = &rtph265.Encoder{
|
||||||
|
PayloadMaxSize: t.udpMaxPayloadSize - 12,
|
||||||
PayloadType: pkt.PayloadType,
|
PayloadType: pkt.PayloadType,
|
||||||
SSRC: &v1,
|
SSRC: &v1,
|
||||||
InitialSequenceNumber: &v2,
|
InitialSequenceNumber: &v2,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func TestH265DynamicParams(t *testing.T) {
|
|||||||
PayloadTyp: 96,
|
PayloadTyp: 96,
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := New(forma, false)
|
p, err := New(1472, forma, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
enc := forma.CreateEncoder()
|
enc := forma.CreateEncoder()
|
||||||
@@ -66,7 +66,7 @@ func TestH265OversizedPackets(t *testing.T) {
|
|||||||
PPS: []byte{byte(h265.NALUType_PPS_NUT) << 1, 16, 17, 18},
|
PPS: []byte{byte(h265.NALUType_PPS_NUT) << 1, 16, 17, 18},
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := New(forma, false)
|
p, err := New(1472, forma, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var out []*rtp.Packet
|
var out []*rtp.Packet
|
||||||
@@ -150,7 +150,7 @@ func TestH265EmptyPacket(t *testing.T) {
|
|||||||
PayloadTyp: 96,
|
PayloadTyp: 96,
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := New(forma, true)
|
p, err := New(1472, forma, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
unit := &UnitH265{
|
unit := &UnitH265{
|
||||||
|
|||||||
@@ -28,17 +28,20 @@ func (d *UnitMPEG4Audio) GetNTP() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type formatProcessorMPEG4Audio struct {
|
type formatProcessorMPEG4Audio struct {
|
||||||
format *format.MPEG4Audio
|
udpMaxPayloadSize int
|
||||||
encoder *rtpmpeg4audio.Encoder
|
format *format.MPEG4Audio
|
||||||
decoder *rtpmpeg4audio.Decoder
|
encoder *rtpmpeg4audio.Encoder
|
||||||
|
decoder *rtpmpeg4audio.Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMPEG4Audio(
|
func newMPEG4Audio(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
forma *format.MPEG4Audio,
|
forma *format.MPEG4Audio,
|
||||||
allocateEncoder bool,
|
allocateEncoder bool,
|
||||||
) (*formatProcessorMPEG4Audio, error) {
|
) (*formatProcessorMPEG4Audio, error) {
|
||||||
t := &formatProcessorMPEG4Audio{
|
t := &formatProcessorMPEG4Audio{
|
||||||
format: forma,
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
|
format: forma,
|
||||||
}
|
}
|
||||||
|
|
||||||
if allocateEncoder {
|
if allocateEncoder {
|
||||||
@@ -58,9 +61,9 @@ func (t *formatProcessorMPEG4Audio) Process(unit Unit, hasNonRTSPReaders bool) e
|
|||||||
pkt.Header.Padding = false
|
pkt.Header.Padding = false
|
||||||
pkt.PaddingSize = 0
|
pkt.PaddingSize = 0
|
||||||
|
|
||||||
if pkt.MarshalSize() > maxPacketSize {
|
if pkt.MarshalSize() > t.udpMaxPayloadSize {
|
||||||
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
||||||
pkt.MarshalSize(), maxPacketSize)
|
pkt.MarshalSize(), t.udpMaxPayloadSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode from RTP
|
// decode from RTP
|
||||||
|
|||||||
@@ -28,17 +28,20 @@ func (d *UnitOpus) GetNTP() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type formatProcessorOpus struct {
|
type formatProcessorOpus struct {
|
||||||
format *format.Opus
|
udpMaxPayloadSize int
|
||||||
encoder *rtpsimpleaudio.Encoder
|
format *format.Opus
|
||||||
decoder *rtpsimpleaudio.Decoder
|
encoder *rtpsimpleaudio.Encoder
|
||||||
|
decoder *rtpsimpleaudio.Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOpus(
|
func newOpus(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
forma *format.Opus,
|
forma *format.Opus,
|
||||||
allocateEncoder bool,
|
allocateEncoder bool,
|
||||||
) (*formatProcessorOpus, error) {
|
) (*formatProcessorOpus, error) {
|
||||||
t := &formatProcessorOpus{
|
t := &formatProcessorOpus{
|
||||||
format: forma,
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
|
format: forma,
|
||||||
}
|
}
|
||||||
|
|
||||||
if allocateEncoder {
|
if allocateEncoder {
|
||||||
@@ -58,9 +61,9 @@ func (t *formatProcessorOpus) Process(unit Unit, hasNonRTSPReaders bool) error {
|
|||||||
pkt.Header.Padding = false
|
pkt.Header.Padding = false
|
||||||
pkt.PaddingSize = 0
|
pkt.PaddingSize = 0
|
||||||
|
|
||||||
if pkt.MarshalSize() > maxPacketSize {
|
if pkt.MarshalSize() > t.udpMaxPayloadSize {
|
||||||
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
||||||
pkt.MarshalSize(), maxPacketSize)
|
pkt.MarshalSize(), t.udpMaxPayloadSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode from RTP
|
// decode from RTP
|
||||||
|
|||||||
@@ -12,27 +12,31 @@ type Processor interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New allocates a Processor.
|
// New allocates a Processor.
|
||||||
func New(forma format.Format, generateRTPPackets bool) (Processor, error) {
|
func New(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
|
forma format.Format,
|
||||||
|
generateRTPPackets bool,
|
||||||
|
) (Processor, error) {
|
||||||
switch forma := forma.(type) {
|
switch forma := forma.(type) {
|
||||||
case *format.H264:
|
case *format.H264:
|
||||||
return newH264(forma, generateRTPPackets)
|
return newH264(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|
||||||
case *format.H265:
|
case *format.H265:
|
||||||
return newH265(forma, generateRTPPackets)
|
return newH265(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|
||||||
case *format.VP8:
|
case *format.VP8:
|
||||||
return newVP8(forma, generateRTPPackets)
|
return newVP8(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|
||||||
case *format.VP9:
|
case *format.VP9:
|
||||||
return newVP9(forma, generateRTPPackets)
|
return newVP9(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|
||||||
case *format.MPEG4Audio:
|
case *format.MPEG4Audio:
|
||||||
return newMPEG4Audio(forma, generateRTPPackets)
|
return newMPEG4Audio(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|
||||||
case *format.Opus:
|
case *format.Opus:
|
||||||
return newOpus(forma, generateRTPPackets)
|
return newOpus(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return newGeneric(forma, generateRTPPackets)
|
return newGeneric(udpMaxPayloadSize, forma, generateRTPPackets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,17 +28,20 @@ func (d *UnitVP8) GetNTP() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type formatProcessorVP8 struct {
|
type formatProcessorVP8 struct {
|
||||||
format *format.VP8
|
udpMaxPayloadSize int
|
||||||
encoder *rtpvp8.Encoder
|
format *format.VP8
|
||||||
decoder *rtpvp8.Decoder
|
encoder *rtpvp8.Encoder
|
||||||
|
decoder *rtpvp8.Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVP8(
|
func newVP8(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
forma *format.VP8,
|
forma *format.VP8,
|
||||||
allocateEncoder bool,
|
allocateEncoder bool,
|
||||||
) (*formatProcessorVP8, error) {
|
) (*formatProcessorVP8, error) {
|
||||||
t := &formatProcessorVP8{
|
t := &formatProcessorVP8{
|
||||||
format: forma,
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
|
format: forma,
|
||||||
}
|
}
|
||||||
|
|
||||||
if allocateEncoder {
|
if allocateEncoder {
|
||||||
@@ -58,9 +61,9 @@ func (t *formatProcessorVP8) Process(unit Unit, hasNonRTSPReaders bool) error {
|
|||||||
pkt.Header.Padding = false
|
pkt.Header.Padding = false
|
||||||
pkt.PaddingSize = 0
|
pkt.PaddingSize = 0
|
||||||
|
|
||||||
if pkt.MarshalSize() > maxPacketSize {
|
if pkt.MarshalSize() > t.udpMaxPayloadSize {
|
||||||
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
||||||
pkt.MarshalSize(), maxPacketSize)
|
pkt.MarshalSize(), t.udpMaxPayloadSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode from RTP
|
// decode from RTP
|
||||||
|
|||||||
@@ -28,17 +28,20 @@ func (d *UnitVP9) GetNTP() time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type formatProcessorVP9 struct {
|
type formatProcessorVP9 struct {
|
||||||
format *format.VP9
|
udpMaxPayloadSize int
|
||||||
encoder *rtpvp9.Encoder
|
format *format.VP9
|
||||||
decoder *rtpvp9.Decoder
|
encoder *rtpvp9.Encoder
|
||||||
|
decoder *rtpvp9.Decoder
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVP9(
|
func newVP9(
|
||||||
|
udpMaxPayloadSize int,
|
||||||
forma *format.VP9,
|
forma *format.VP9,
|
||||||
allocateEncoder bool,
|
allocateEncoder bool,
|
||||||
) (*formatProcessorVP9, error) {
|
) (*formatProcessorVP9, error) {
|
||||||
t := &formatProcessorVP9{
|
t := &formatProcessorVP9{
|
||||||
format: forma,
|
udpMaxPayloadSize: udpMaxPayloadSize,
|
||||||
|
format: forma,
|
||||||
}
|
}
|
||||||
|
|
||||||
if allocateEncoder {
|
if allocateEncoder {
|
||||||
@@ -58,9 +61,9 @@ func (t *formatProcessorVP9) Process(unit Unit, hasNonRTSPReaders bool) error {
|
|||||||
pkt.Header.Padding = false
|
pkt.Header.Padding = false
|
||||||
pkt.PaddingSize = 0
|
pkt.PaddingSize = 0
|
||||||
|
|
||||||
if pkt.MarshalSize() > maxPacketSize {
|
if pkt.MarshalSize() > t.udpMaxPayloadSize {
|
||||||
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
return fmt.Errorf("payload size (%d) is greater than maximum allowed (%d)",
|
||||||
pkt.MarshalSize(), maxPacketSize)
|
pkt.MarshalSize(), t.udpMaxPayloadSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode from RTP
|
// decode from RTP
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ writeTimeout: 10s
|
|||||||
# Number of read buffers.
|
# Number of read buffers.
|
||||||
# A higher value allows a wider throughput, a lower value allows to save RAM.
|
# A higher value allows a wider throughput, a lower value allows to save RAM.
|
||||||
readBufferCount: 512
|
readBufferCount: 512
|
||||||
|
# Maximum size of payload of outgoing UDP packets.
|
||||||
|
# This can be decreased to avoid fragmentation on networks with a low UDP MTU.
|
||||||
|
udpMaxPayloadSize: 1472
|
||||||
|
|
||||||
# HTTP URL to perform external authentication.
|
# HTTP URL to perform external authentication.
|
||||||
# Every time a user wants to authenticate, the server calls this URL
|
# Every time a user wants to authenticate, the server calls this URL
|
||||||
|
|||||||
Reference in New Issue
Block a user