mirror of
https://github.com/aler9/gortsplib
synced 2025-09-29 20:42:09 +08:00
use random UUIDs as media IDs (#163)
* remove Medias.Clone(), Media.Clone(), Format.Clone() * server: use random UUIDs as media IDs * client: use random UUIDs as media IDs
This commit is contained in:
@@ -3,7 +3,6 @@ package gortsplib
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -72,7 +71,7 @@ func readAll(c *Client, ur string, cb func(*media.Media, format.Format, *rtp.Pac
|
||||
}
|
||||
|
||||
func TestClientPlayFormats(t *testing.T) {
|
||||
media1 := testH264Media.Clone()
|
||||
media1 := testH264Media
|
||||
|
||||
media2 := &media.Media{
|
||||
Type: media.TypeAudio,
|
||||
@@ -156,7 +155,7 @@ func TestClientPlayFormats(t *testing.T) {
|
||||
req, err := conn.ReadRequest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL(fmt.Sprintf("rtsp://localhost:8554/teststream/mediaID=%d", i)), req.URL)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/"+medias[i].Control), req.URL)
|
||||
|
||||
var inTH headers.Transport
|
||||
err = inTH.Unmarshal(req.Header["Transport"])
|
||||
@@ -306,7 +305,7 @@ func TestClientPlay(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL(
|
||||
scheme+"://"+listenIP+":8554/test/stream?param=value/mediaID="+strconv.FormatInt(int64(i), 10)), req.URL)
|
||||
scheme+"://"+listenIP+":8554/test/stream?param=value/"+medias[i].Control), req.URL)
|
||||
|
||||
var inTH headers.Transport
|
||||
err = inTH.Unmarshal(req.Header["Transport"])
|
||||
@@ -542,9 +541,22 @@ func TestClientPlayPartial(t *testing.T) {
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://"+listenIP+":8554/teststream"), req.URL)
|
||||
|
||||
forma := &format.Generic{
|
||||
PayloadTyp: 96,
|
||||
RTPMap: "private/90000",
|
||||
}
|
||||
err = forma.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
medias := media.Medias{
|
||||
testH264Media.Clone(),
|
||||
testH264Media.Clone(),
|
||||
&media.Media{
|
||||
Type: "application",
|
||||
Formats: []format.Format{forma},
|
||||
},
|
||||
&media.Media{
|
||||
Type: "application",
|
||||
Formats: []format.Format{forma},
|
||||
},
|
||||
}
|
||||
medias.SetControls()
|
||||
|
||||
@@ -561,7 +573,7 @@ func TestClientPlayPartial(t *testing.T) {
|
||||
req, err = conn.ReadRequest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://"+listenIP+":8554/teststream/mediaID=1"), req.URL)
|
||||
require.Equal(t, mustParseURL("rtsp://"+listenIP+":8554/teststream/"+medias[1].Control), req.URL)
|
||||
|
||||
var inTH headers.Transport
|
||||
err = inTH.Unmarshal(req.Header["Transport"])
|
||||
@@ -688,7 +700,7 @@ func TestClientPlayContentBase(t *testing.T) {
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
switch ca {
|
||||
@@ -720,7 +732,7 @@ func TestClientPlayContentBase(t *testing.T) {
|
||||
req, err = conn.ReadRequest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"), req.URL)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/"+medias[0].Control), req.URL)
|
||||
|
||||
var inTH headers.Transport
|
||||
err = inTH.Unmarshal(req.Header["Transport"])
|
||||
@@ -818,7 +830,7 @@ func TestClientPlayAnyPort(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -972,7 +984,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -1057,7 +1069,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) {
|
||||
go func() {
|
||||
defer close(serverDone)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
func() {
|
||||
@@ -1116,7 +1128,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) {
|
||||
req, err = conn.ReadRequest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"), req.URL)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/"+medias[0].Control), req.URL)
|
||||
|
||||
var inTH headers.Transport
|
||||
err = inTH.Unmarshal(req.Header["Transport"])
|
||||
@@ -1212,7 +1224,7 @@ func TestClientPlayAutomaticProtocol(t *testing.T) {
|
||||
req, err = conn.ReadRequest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"), req.URL)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/"+medias[0].Control), req.URL)
|
||||
|
||||
err = v.ValidateRequest(req, nil)
|
||||
require.NoError(t, err)
|
||||
@@ -1317,7 +1329,7 @@ func TestClientPlayDifferentInterleavedIDs(t *testing.T) {
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -1333,7 +1345,7 @@ func TestClientPlayDifferentInterleavedIDs(t *testing.T) {
|
||||
req, err = conn.ReadRequest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"), req.URL)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream/"+medias[0].Control), req.URL)
|
||||
|
||||
var inTH headers.Transport
|
||||
err = inTH.Unmarshal(req.Header["Transport"])
|
||||
@@ -1512,7 +1524,7 @@ func TestClientPlayRedirect(t *testing.T) {
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
}
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -1673,7 +1685,7 @@ func TestClientPlayPause(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -1841,7 +1853,7 @@ func TestClientPlayRTCPReport(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -2019,7 +2031,7 @@ func TestClientPlayErrorTimeout(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -2165,7 +2177,7 @@ func TestClientPlayIgnoreTCPInvalidMedia(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -2288,7 +2300,7 @@ func TestClientPlaySeek(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -2452,7 +2464,7 @@ func TestClientPlayKeepaliveFromSession(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -2575,7 +2587,7 @@ func TestClientPlayDifferentSource(t *testing.T) {
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/test/stream?param=value"), req.URL)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -2591,7 +2603,7 @@ func TestClientPlayDifferentSource(t *testing.T) {
|
||||
req, err = conn.ReadRequest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/test/stream?param=value/mediaID=0"), req.URL)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/test/stream?param=value/"+medias[0].Control), req.URL)
|
||||
|
||||
var inTH headers.Transport
|
||||
err = inTH.Unmarshal(req.Header["Transport"])
|
||||
|
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/aler9/gortsplib/v2/pkg/format"
|
||||
"github.com/aler9/gortsplib/v2/pkg/headers"
|
||||
"github.com/aler9/gortsplib/v2/pkg/media"
|
||||
"github.com/aler9/gortsplib/v2/pkg/sdp"
|
||||
"github.com/aler9/gortsplib/v2/pkg/url"
|
||||
)
|
||||
|
||||
@@ -155,6 +156,10 @@ func TestClientRecordSerial(t *testing.T) {
|
||||
require.Equal(t, base.Announce, req.Method)
|
||||
require.Equal(t, mustParseURL(scheme+"://localhost:8554/teststream"), req.URL)
|
||||
|
||||
var desc sdp.SessionDescription
|
||||
err = desc.Unmarshal(req.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
})
|
||||
@@ -163,7 +168,8 @@ func TestClientRecordSerial(t *testing.T) {
|
||||
req, err = conn.ReadRequest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, base.Setup, req.Method)
|
||||
require.Equal(t, mustParseURL(scheme+"://localhost:8554/teststream/mediaID=0"), req.URL)
|
||||
require.Equal(t, mustParseURL(
|
||||
scheme+"://localhost:8554/teststream/"+controlAttribute(desc.MediaDescriptions[0])), req.URL)
|
||||
|
||||
var inTH headers.Transport
|
||||
err = inTH.Unmarshal(req.Header["Transport"])
|
||||
@@ -275,7 +281,7 @@ func TestClientRecordSerial(t *testing.T) {
|
||||
}(),
|
||||
}
|
||||
|
||||
medi := testH264Media.Clone()
|
||||
medi := testH264Media
|
||||
medias := media.Medias{medi}
|
||||
medias.SetControls()
|
||||
|
||||
@@ -431,7 +437,7 @@ func TestClientRecordParallel(t *testing.T) {
|
||||
writerDone := make(chan struct{})
|
||||
defer func() { <-writerDone }()
|
||||
|
||||
medi := testH264Media.Clone()
|
||||
medi := testH264Media
|
||||
medias := media.Medias{medi}
|
||||
medias.SetControls()
|
||||
|
||||
@@ -584,7 +590,7 @@ func TestClientRecordPauseSerial(t *testing.T) {
|
||||
}(),
|
||||
}
|
||||
|
||||
medi := testH264Media.Clone()
|
||||
medi := testH264Media
|
||||
medias := media.Medias{medi}
|
||||
medias.SetControls()
|
||||
|
||||
@@ -715,7 +721,7 @@ func TestClientRecordPauseParallel(t *testing.T) {
|
||||
}(),
|
||||
}
|
||||
|
||||
medi := testH264Media.Clone()
|
||||
medi := testH264Media
|
||||
medias := media.Medias{medi}
|
||||
medias.SetControls()
|
||||
|
||||
@@ -855,7 +861,7 @@ func TestClientRecordAutomaticProtocol(t *testing.T) {
|
||||
|
||||
c := Client{}
|
||||
|
||||
medi := testH264Media.Clone()
|
||||
medi := testH264Media
|
||||
medias := media.Medias{medi}
|
||||
medias.SetControls()
|
||||
|
||||
@@ -1038,7 +1044,7 @@ func TestClientRecordDecodeErrors(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = record(&c, "rtsp://localhost:8554/stream", medias, nil)
|
||||
@@ -1196,7 +1202,7 @@ func TestClientRecordRTCPReport(t *testing.T) {
|
||||
senderReportPeriod: 500 * time.Millisecond,
|
||||
}
|
||||
|
||||
medi := testH264Media.Clone()
|
||||
medi := testH264Media
|
||||
medias := media.Medias{medi}
|
||||
medias.SetControls()
|
||||
|
||||
@@ -1326,7 +1332,7 @@ func TestClientRecordIgnoreTCPRTPPackets(t *testing.T) {
|
||||
}(),
|
||||
}
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = record(&c, "rtsp://localhost:8554/teststream", medias,
|
||||
|
@@ -106,7 +106,7 @@ func TestClientSession(t *testing.T) {
|
||||
|
||||
require.Equal(t, base.HeaderValue{"123456"}, req.Header["Session"])
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -183,7 +183,7 @@ func TestClientAuth(t *testing.T) {
|
||||
err = v.ValidateRequest(req, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
@@ -243,7 +243,7 @@ func TestClientDescribeCharset(t *testing.T) {
|
||||
require.Equal(t, base.Describe, req.Method)
|
||||
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
|
||||
err = conn.WriteResponse(&base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
|
1
go.mod
1
go.mod
@@ -4,6 +4,7 @@ go 1.17
|
||||
|
||||
require (
|
||||
github.com/asticode/go-astits v1.10.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/pion/rtcp v1.2.9
|
||||
github.com/pion/rtp v1.7.13
|
||||
github.com/pion/sdp/v3 v3.0.5
|
||||
|
2
go.sum
2
go.sum
@@ -4,6 +4,8 @@ github.com/asticode/go-astits v1.10.0 h1:ixKsRl84nWtjgHWcWKTDkUHNQ4kxbf9nKmjuSCn
|
||||
github.com/asticode/go-astits v1.10.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
|
||||
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
|
||||
github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U=
|
||||
|
@@ -48,9 +48,6 @@ type Format interface {
|
||||
// Marshal encodes the format in SDP format.
|
||||
Marshal() (string, string)
|
||||
|
||||
// Clone clones the format.
|
||||
Clone() Format
|
||||
|
||||
// PTSEqualsDTS checks whether PTS is equal to DTS in the RTP packet.
|
||||
PTSEqualsDTS(*rtp.Packet) bool
|
||||
}
|
||||
|
@@ -52,13 +52,6 @@ func (t *G711) Marshal() (string, string) {
|
||||
return "PCMA/8000", ""
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *G711) Clone() Format {
|
||||
return &G711{
|
||||
MULaw: t.MULaw,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *G711) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -22,14 +22,6 @@ func TestG711Attributes(t *testing.T) {
|
||||
require.Equal(t, uint8(0), format.PayloadType())
|
||||
}
|
||||
|
||||
func TestG711Clone(t *testing.T) {
|
||||
format := &G711{}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestG711MediaDescription(t *testing.T) {
|
||||
t.Run("pcma", func(t *testing.T) {
|
||||
format := &G711{}
|
||||
|
@@ -41,11 +41,6 @@ func (t *G722) Marshal() (string, string) {
|
||||
return "G722/8000", ""
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *G722) Clone() Format {
|
||||
return &G722{}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *G722) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -15,14 +15,6 @@ func TestG722Attributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestG722Clone(t *testing.T) {
|
||||
format := &G722{}
|
||||
|
||||
clone := format.Clone()
|
||||
// require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestG722MediaDescription(t *testing.T) {
|
||||
format := &G722{}
|
||||
|
||||
|
@@ -95,16 +95,6 @@ func (t *Generic) Marshal() (string, string) {
|
||||
return t.RTPMap, t.FMTP
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *Generic) Clone() Format {
|
||||
return &Generic{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
RTPMap: t.RTPMap,
|
||||
FMTP: t.FMTP,
|
||||
ClockRat: t.ClockRat,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *Generic) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -23,21 +23,6 @@ func TestGenericAttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestGenericClone(t *testing.T) {
|
||||
format := &Generic{
|
||||
PayloadTyp: 98,
|
||||
RTPMap: "H265/90000",
|
||||
FMTP: "profile-id=1; sprop-vps=QAEMAf//AWAAAAMAAAMAAAMAAAMAlqwJ; " +
|
||||
"sprop-sps=QgEBAWAAAAMAAAMAAAMAAAMAlqADwIAQ5Za5JMmuWcBSSgAAB9AAAHUwgkA=; sprop-pps=RAHgdrAwxmQ=",
|
||||
}
|
||||
err := format.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestGenericMediaDescription(t *testing.T) {
|
||||
format := &Generic{
|
||||
PayloadTyp: 98,
|
||||
|
@@ -175,16 +175,6 @@ func (t *H264) Marshal() (string, string) {
|
||||
return "H264/90000", fmtp
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *H264) Clone() Format {
|
||||
return &H264{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
SPS: t.SafeSPS(),
|
||||
PPS: t.SafePPS(),
|
||||
PacketizationMode: t.PacketizationMode,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *H264) PTSEqualsDTS(pkt *rtp.Packet) bool {
|
||||
return rtpH264ContainsIDR(pkt)
|
||||
|
@@ -42,19 +42,6 @@ func TestH264PTSEqualsDTS(t *testing.T) {
|
||||
}))
|
||||
}
|
||||
|
||||
func TestH264Clone(t *testing.T) {
|
||||
format := &H264{
|
||||
PayloadTyp: 96,
|
||||
SPS: []byte{0x01, 0x02},
|
||||
PPS: []byte{0x03, 0x04},
|
||||
PacketizationMode: 1,
|
||||
}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestH264MediaDescription(t *testing.T) {
|
||||
t.Run("standard", func(t *testing.T) {
|
||||
format := &H264{
|
||||
|
@@ -117,17 +117,6 @@ func (t *H265) Marshal() (string, string) {
|
||||
return "H265/90000", fmtp
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *H265) Clone() Format {
|
||||
return &H265{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
VPS: t.SafeVPS(),
|
||||
SPS: t.SafeSPS(),
|
||||
PPS: t.SafePPS(),
|
||||
MaxDONDiff: t.MaxDONDiff,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *H265) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -30,19 +30,6 @@ func TestH265Attributes(t *testing.T) {
|
||||
require.Equal(t, []byte{0x0B, 0x0C}, format.SafePPS())
|
||||
}
|
||||
|
||||
func TestH265Clone(t *testing.T) {
|
||||
format := &H265{
|
||||
PayloadTyp: 96,
|
||||
VPS: []byte{0x01, 0x02},
|
||||
SPS: []byte{0x03, 0x04},
|
||||
PPS: []byte{0x05, 0x06},
|
||||
}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestH265MediaDescription(t *testing.T) {
|
||||
format := &H265{
|
||||
PayloadTyp: 96,
|
||||
|
@@ -31,11 +31,6 @@ func (t *JPEG) Marshal() (string, string) {
|
||||
return "JPEG/90000", ""
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *JPEG) Clone() Format {
|
||||
return &JPEG{}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *JPEG) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -15,14 +15,6 @@ func TestJPEGAttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestJPEGClone(t *testing.T) {
|
||||
format := &JPEG{}
|
||||
|
||||
clone := format.Clone()
|
||||
// require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestJPEGMediaDescription(t *testing.T) {
|
||||
format := &JPEG{}
|
||||
|
||||
|
@@ -89,16 +89,6 @@ func (t *LPCM) Marshal() (string, string) {
|
||||
"/" + strconv.FormatInt(int64(t.ChannelCount), 10), ""
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *LPCM) Clone() Format {
|
||||
return &LPCM{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
BitDepth: t.BitDepth,
|
||||
SampleRate: t.SampleRate,
|
||||
ChannelCount: t.ChannelCount,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *LPCM) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -20,19 +20,6 @@ func TestLPCMAttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestTracLPCMClone(t *testing.T) {
|
||||
format := &LPCM{
|
||||
PayloadTyp: 96,
|
||||
BitDepth: 16,
|
||||
SampleRate: 48000,
|
||||
ChannelCount: 2,
|
||||
}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestLPCMMediaDescription(t *testing.T) {
|
||||
format := &LPCM{
|
||||
PayloadTyp: 96,
|
||||
|
@@ -31,11 +31,6 @@ func (t *MPEG2Audio) Marshal() (string, string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *MPEG2Audio) Clone() Format {
|
||||
return &MPEG2Audio{}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *MPEG2Audio) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -15,14 +15,6 @@ func TestMPEG2AudioAttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestMPEG2AudioClone(t *testing.T) {
|
||||
format := &MPEG2Audio{}
|
||||
|
||||
clone := format.Clone()
|
||||
// require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestMPEG2AudioMediaDescription(t *testing.T) {
|
||||
format := &MPEG2Audio{}
|
||||
|
||||
|
@@ -31,11 +31,6 @@ func (t *MPEG2Video) Marshal() (string, string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *MPEG2Video) Clone() Format {
|
||||
return &MPEG2Video{}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *MPEG2Video) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -15,14 +15,6 @@ func TestMPEG2VideoAttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestMPEG2VideoClone(t *testing.T) {
|
||||
format := &MPEG2Video{}
|
||||
|
||||
clone := format.Clone()
|
||||
// require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestMPEG2VideoMediaDescription(t *testing.T) {
|
||||
format := &MPEG2Video{}
|
||||
|
||||
|
@@ -140,17 +140,6 @@ func (t *MPEG4Audio) Marshal() (string, string) {
|
||||
"/" + strconv.FormatInt(int64(t.Config.ChannelCount), 10), fmtp
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *MPEG4Audio) Clone() Format {
|
||||
return &MPEG4Audio{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
Config: t.Config,
|
||||
SizeLength: t.SizeLength,
|
||||
IndexLength: t.IndexLength,
|
||||
IndexDeltaLength: t.IndexDeltaLength,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *MPEG4Audio) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -27,24 +27,6 @@ func TestMPEG4AudioAttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestMPEG4AudioClone(t *testing.T) {
|
||||
format := &MPEG4Audio{
|
||||
PayloadTyp: 96,
|
||||
Config: &mpeg4audio.Config{
|
||||
Type: mpeg4audio.ObjectTypeAACLC,
|
||||
SampleRate: 48000,
|
||||
ChannelCount: 2,
|
||||
},
|
||||
SizeLength: 13,
|
||||
IndexLength: 3,
|
||||
IndexDeltaLength: 3,
|
||||
}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestMPEG4AudioMediaDescription(t *testing.T) {
|
||||
format := &MPEG4Audio{
|
||||
PayloadTyp: 96,
|
||||
|
@@ -68,15 +68,6 @@ func (t *Opus) Marshal() (string, string) {
|
||||
"/" + strconv.FormatInt(int64(t.ChannelCount), 10), fmtp
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *Opus) Clone() Format {
|
||||
return &Opus{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
SampleRate: t.SampleRate,
|
||||
ChannelCount: t.ChannelCount,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *Opus) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -19,18 +19,6 @@ func TestOpusAttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestTracOpusClone(t *testing.T) {
|
||||
format := &Opus{
|
||||
PayloadTyp: 96,
|
||||
SampleRate: 48000,
|
||||
ChannelCount: 2,
|
||||
}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestOpusMediaDescription(t *testing.T) {
|
||||
format := &Opus{
|
||||
PayloadTyp: 96,
|
||||
|
@@ -92,16 +92,6 @@ func (t *Vorbis) Marshal() (string, string) {
|
||||
"configuration=" + base64.StdEncoding.EncodeToString(t.Configuration)
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *Vorbis) Clone() Format {
|
||||
return &Vorbis{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
SampleRate: t.SampleRate,
|
||||
ChannelCount: t.ChannelCount,
|
||||
Configuration: t.Configuration,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *Vorbis) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -20,19 +20,6 @@ func TestVorbisAttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestTracVorbisClone(t *testing.T) {
|
||||
format := &Vorbis{
|
||||
PayloadTyp: 96,
|
||||
SampleRate: 48000,
|
||||
ChannelCount: 2,
|
||||
Configuration: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestVorbisMediaDescription(t *testing.T) {
|
||||
format := &Vorbis{
|
||||
PayloadTyp: 96,
|
||||
|
@@ -88,15 +88,6 @@ func (t *VP8) Marshal() (string, string) {
|
||||
return "VP8/90000", fmtp
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *VP8) Clone() Format {
|
||||
return &VP8{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
MaxFR: t.MaxFR,
|
||||
MaxFS: t.MaxFS,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *VP8) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -17,20 +17,6 @@ func TestVP8ttributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestVP8Clone(t *testing.T) {
|
||||
maxFR := 123
|
||||
maxFS := 456
|
||||
format := &VP8{
|
||||
PayloadTyp: 96,
|
||||
MaxFR: &maxFR,
|
||||
MaxFS: &maxFS,
|
||||
}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestVP8MediaDescription(t *testing.T) {
|
||||
maxFR := 123
|
||||
maxFS := 456
|
||||
|
@@ -100,16 +100,6 @@ func (t *VP9) Marshal() (string, string) {
|
||||
return "VP9/90000", fmtp
|
||||
}
|
||||
|
||||
// Clone implements Format.
|
||||
func (t *VP9) Clone() Format {
|
||||
return &VP9{
|
||||
PayloadTyp: t.PayloadTyp,
|
||||
MaxFR: t.MaxFR,
|
||||
MaxFS: t.MaxFS,
|
||||
ProfileID: t.ProfileID,
|
||||
}
|
||||
}
|
||||
|
||||
// PTSEqualsDTS implements Format.
|
||||
func (t *VP9) PTSEqualsDTS(*rtp.Packet) bool {
|
||||
return true
|
||||
|
@@ -17,22 +17,6 @@ func TestVP9Attributes(t *testing.T) {
|
||||
require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{}))
|
||||
}
|
||||
|
||||
func TestVP9Clone(t *testing.T) {
|
||||
maxFR := 123
|
||||
maxFS := 456
|
||||
profileID := 789
|
||||
format := &VP9{
|
||||
PayloadTyp: 96,
|
||||
MaxFR: &maxFR,
|
||||
MaxFS: &maxFS,
|
||||
ProfileID: &profileID,
|
||||
}
|
||||
|
||||
clone := format.Clone()
|
||||
require.NotSame(t, format, clone)
|
||||
require.Equal(t, format, clone)
|
||||
}
|
||||
|
||||
func TestVP9MediaDescription(t *testing.T) {
|
||||
maxFR := 123
|
||||
maxFS := 456
|
||||
|
@@ -103,21 +103,6 @@ func (m *Media) Marshal() *psdp.MediaDescription {
|
||||
return md
|
||||
}
|
||||
|
||||
// Clone clones the media.
|
||||
func (m Media) Clone() *Media {
|
||||
ret := &Media{
|
||||
Type: m.Type,
|
||||
Control: m.Control,
|
||||
Formats: make([]format.Format, len(m.Formats)),
|
||||
}
|
||||
|
||||
for i, format := range m.Formats {
|
||||
ret.Formats[i] = format.Clone()
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// URL returns the media URL.
|
||||
func (m Media) URL(contentBase *url.URL) (*url.URL, error) {
|
||||
if contentBase == nil {
|
||||
|
@@ -3,8 +3,8 @@ package media
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/google/uuid"
|
||||
psdp "github.com/pion/sdp/v3"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/sdp"
|
||||
@@ -65,32 +65,15 @@ func (ms Medias) Marshal(multicast bool) *sdp.SessionDescription {
|
||||
return sout
|
||||
}
|
||||
|
||||
// Clone clones the media list.
|
||||
func (ms Medias) Clone() Medias {
|
||||
ret := make(Medias, len(ms))
|
||||
for i, media := range ms {
|
||||
ret[i] = media.Clone()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// CloneAndSetControls clones the media list and sets the control attribute
|
||||
// of all medias in the list.
|
||||
func (ms Medias) CloneAndSetControls() Medias {
|
||||
ret := ms.Clone()
|
||||
ret.SetControls()
|
||||
return ret
|
||||
}
|
||||
|
||||
// SetControls sets the control attribute of all medias in the list.
|
||||
func (ms Medias) SetControls() {
|
||||
for i, media := range ms {
|
||||
media.Control = "mediaID=" + strconv.FormatInt(int64(i), 10)
|
||||
for _, media := range ms {
|
||||
media.Control = "mediaUUID=" + uuid.New().String()
|
||||
}
|
||||
}
|
||||
|
||||
// FindFormat finds a certain format among all the formats in all the medias.
|
||||
// If the format is found, it is inserted into forma, and format media is returned.
|
||||
// If the format is found, it is inserted into forma, and its media is returned.
|
||||
func (ms Medias) FindFormat(forma interface{}) *Media {
|
||||
for _, media := range ms {
|
||||
for _, formak := range media.Formats {
|
||||
|
@@ -3,14 +3,17 @@ package gortsplib
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/rtp"
|
||||
psdp "github.com/pion/sdp/v3"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/ipv4"
|
||||
|
||||
@@ -49,6 +52,36 @@ func multicastCapableIP(t *testing.T) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func controlAttribute(md *psdp.MediaDescription) string {
|
||||
v, _ := md.Attribute("control")
|
||||
return v
|
||||
}
|
||||
|
||||
func doDescribe(conn *conn.Conn) (*sdp.SessionDescription, error) {
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Describe,
|
||||
URL: mustParseURL("rtsp://localhost:8554/pa"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.StatusCode != base.StatusOK {
|
||||
return nil, errors.New("bad status code")
|
||||
}
|
||||
|
||||
var desc sdp.SessionDescription
|
||||
err = desc.Unmarshal(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &desc, err
|
||||
}
|
||||
|
||||
func TestServerPlaySetupPath(t *testing.T) {
|
||||
for _, ca := range []struct {
|
||||
name string
|
||||
@@ -57,12 +90,12 @@ func TestServerPlaySetupPath(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
"normal",
|
||||
"rtsp://localhost:8554/teststream/mediaID=2",
|
||||
"rtsp://localhost:8554/teststream/[control2]",
|
||||
"teststream",
|
||||
},
|
||||
{
|
||||
"with query",
|
||||
"rtsp://localhost:8554/teststream?testing=123/mediaID=4",
|
||||
"rtsp://localhost:8554/teststream?testing=123/[control4]",
|
||||
"teststream",
|
||||
},
|
||||
{
|
||||
@@ -73,7 +106,7 @@ func TestServerPlaySetupPath(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"subpath",
|
||||
"rtsp://localhost:8554/test/stream/mediaID=0",
|
||||
"rtsp://localhost:8554/test/stream/[control0]",
|
||||
"test/stream",
|
||||
},
|
||||
{
|
||||
@@ -83,17 +116,27 @@ func TestServerPlaySetupPath(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"subpath with query",
|
||||
"rtsp://localhost:8554/test/stream?testing=123/mediaID=4",
|
||||
"rtsp://localhost:8554/test/stream?testing=123/[control4]",
|
||||
"test/stream",
|
||||
},
|
||||
} {
|
||||
t.Run(ca.name, func(t *testing.T) {
|
||||
medi := testH264Media.Clone()
|
||||
stream := NewServerStream(media.Medias{medi, medi, medi, medi, medi})
|
||||
stream := NewServerStream(media.Medias{
|
||||
testH264Media,
|
||||
testH264Media,
|
||||
testH264Media,
|
||||
testH264Media,
|
||||
testH264Media,
|
||||
})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
require.Equal(t, ca.path, ctx.Path)
|
||||
return &base.Response{
|
||||
@@ -113,6 +156,9 @@ func TestServerPlaySetupPath(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
th := &headers.Transport{
|
||||
Protocol: headers.TransportProtocolTCP,
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -126,11 +172,16 @@ func TestServerPlaySetupPath(t *testing.T) {
|
||||
InterleavedIDs: &[2]int{0, 1},
|
||||
}
|
||||
|
||||
for i, md := range desc.MediaDescriptions {
|
||||
v, _ := md.Attribute("control")
|
||||
ca.url = strings.ReplaceAll(ca.url, "[control"+strconv.FormatInt(int64(i), 10)+"]", v)
|
||||
}
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL(ca.url),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": th.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -149,7 +200,7 @@ func TestServerPlaySetupErrors(t *testing.T) {
|
||||
t.Run(ca, func(t *testing.T) {
|
||||
nconnClosed := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
if ca == "closed stream" {
|
||||
stream.Close()
|
||||
} else {
|
||||
@@ -171,6 +222,11 @@ func TestServerPlaySetupErrors(t *testing.T) {
|
||||
}
|
||||
close(nconnClosed)
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -189,6 +245,9 @@ func TestServerPlaySetupErrors(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
th := &headers.Transport{
|
||||
Protocol: headers.TransportProtocolTCP,
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -204,9 +263,9 @@ func TestServerPlaySetupErrors(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": th.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -223,9 +282,9 @@ func TestServerPlaySetupErrors(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/test12stream/mediaID=1"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/test12stream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Transport": th.Marshal(),
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
@@ -244,9 +303,9 @@ func TestServerPlaySetupErrors(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"4"},
|
||||
"Transport": th.Marshal(),
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
@@ -265,7 +324,7 @@ func TestServerPlaySetupErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerPlaySetupErrorSameUDPPortsAndIP(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
first := int32(1)
|
||||
errorRecv := make(chan struct{})
|
||||
@@ -279,6 +338,11 @@ func TestServerPlaySetupErrorSameUDPPortsAndIP(t *testing.T) {
|
||||
close(errorRecv)
|
||||
}
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -318,11 +382,14 @@ func TestServerPlaySetupErrorSameUDPPortsAndIP(t *testing.T) {
|
||||
ClientPorts: &[2]int{35466, 35467},
|
||||
}
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -352,7 +419,7 @@ func TestServerPlay(t *testing.T) {
|
||||
sessionClosed := make(chan struct{})
|
||||
framesReceived := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
counter := uint64(0)
|
||||
@@ -373,6 +440,11 @@ func TestServerPlay(t *testing.T) {
|
||||
onSessionClose: func(ctx *ServerHandlerOnSessionCloseCtx) {
|
||||
close(sessionClosed)
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -451,6 +523,9 @@ func TestServerPlay(t *testing.T) {
|
||||
|
||||
<-nconnOpened
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTH := &headers.Transport{
|
||||
Mode: func() *headers.TransportMode {
|
||||
v := headers.TransportModePlay
|
||||
@@ -479,9 +554,9 @@ func TestServerPlay(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -555,7 +630,7 @@ func TestServerPlay(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://" + listenIP + ":8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -698,11 +773,16 @@ func TestServerPlayDecodeErrors(t *testing.T) {
|
||||
t.Run(ca.proto+" "+ca.name, func(t *testing.T) {
|
||||
errorRecv := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -744,6 +824,9 @@ func TestServerPlayDecodeErrors(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTH := &headers.Transport{
|
||||
Mode: func() *headers.TransportMode {
|
||||
v := headers.TransportModePlay
|
||||
@@ -765,9 +848,9 @@ func TestServerPlayDecodeErrors(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -799,7 +882,7 @@ func TestServerPlayDecodeErrors(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -842,11 +925,16 @@ func TestServerPlayDecodeErrors(t *testing.T) {
|
||||
func TestServerPlayRTCPReport(t *testing.T) {
|
||||
for _, ca := range []string{"udp", "tcp"} {
|
||||
t.Run(ca, func(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -873,6 +961,9 @@ func TestServerPlayRTCPReport(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTH := &headers.Transport{
|
||||
Mode: func() *headers.TransportMode {
|
||||
v := headers.TransportModePlay
|
||||
@@ -894,9 +985,9 @@ func TestServerPlayRTCPReport(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -923,7 +1014,7 @@ func TestServerPlayRTCPReport(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -975,7 +1066,7 @@ func TestServerPlayRTCPReport(t *testing.T) {
|
||||
Method: base.Teardown,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"CSeq": base.HeaderValue{"4"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -986,7 +1077,7 @@ func TestServerPlayRTCPReport(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerPlayVLCMulticast(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
listenIP := multicastCapableIP(t)
|
||||
@@ -1035,7 +1126,7 @@ func TestServerPlayTCPResponseBeforeFrames(t *testing.T) {
|
||||
writerDone := make(chan struct{})
|
||||
writerTerminate := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
@@ -1045,6 +1136,11 @@ func TestServerPlayTCPResponseBeforeFrames(t *testing.T) {
|
||||
close(writerTerminate)
|
||||
<-writerDone
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -1087,11 +1183,14 @@ func TestServerPlayTCPResponseBeforeFrames(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": headers.Transport{
|
||||
Protocol: headers.TransportProtocolTCP,
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -1117,7 +1216,7 @@ func TestServerPlayTCPResponseBeforeFrames(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1129,11 +1228,16 @@ func TestServerPlayTCPResponseBeforeFrames(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerPlayPlayPlay(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -1159,11 +1263,14 @@ func TestServerPlayPlayPlay(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": headers.Transport{
|
||||
Protocol: headers.TransportProtocolUDP,
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -1189,7 +1296,7 @@ func TestServerPlayPlayPlay(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1200,7 +1307,7 @@ func TestServerPlayPlayPlay(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"CSeq": base.HeaderValue{"4"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1213,7 +1320,7 @@ func TestServerPlayPlayPausePlay(t *testing.T) {
|
||||
writerDone := make(chan struct{})
|
||||
writerTerminate := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
@@ -1222,6 +1329,11 @@ func TestServerPlayPlayPausePlay(t *testing.T) {
|
||||
close(writerTerminate)
|
||||
<-writerDone
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -1269,11 +1381,14 @@ func TestServerPlayPlayPausePlay(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": headers.Transport{
|
||||
Protocol: headers.TransportProtocolTCP,
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -1333,7 +1448,7 @@ func TestServerPlayPlayPausePause(t *testing.T) {
|
||||
writerDone := make(chan struct{})
|
||||
writerTerminate := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
@@ -1342,6 +1457,11 @@ func TestServerPlayPlayPausePause(t *testing.T) {
|
||||
close(writerTerminate)
|
||||
<-writerDone
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -1386,11 +1506,14 @@ func TestServerPlayPlayPausePause(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": headers.Transport{
|
||||
Protocol: headers.TransportProtocolTCP,
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -1416,7 +1539,7 @@ func TestServerPlayPlayPausePause(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1427,7 +1550,7 @@ func TestServerPlayPlayPausePause(t *testing.T) {
|
||||
Method: base.Pause,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"4"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1441,7 +1564,7 @@ func TestServerPlayPlayPausePause(t *testing.T) {
|
||||
Method: base.Pause,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"5"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1461,7 +1584,7 @@ func TestServerPlayTimeout(t *testing.T) {
|
||||
t.Run(transport, func(t *testing.T) {
|
||||
sessionClosed := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
@@ -1469,10 +1592,10 @@ func TestServerPlayTimeout(t *testing.T) {
|
||||
onSessionClose: func(ctx *ServerHandlerOnSessionCloseCtx) {
|
||||
close(sessionClosed)
|
||||
},
|
||||
onAnnounce: func(ctx *ServerHandlerOnAnnounceCtx) (*base.Response, error) {
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, nil
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
@@ -1510,6 +1633,9 @@ func TestServerPlayTimeout(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTH := &headers.Transport{
|
||||
Mode: func() *headers.TransportMode {
|
||||
v := headers.TransportModePlay
|
||||
@@ -1532,9 +1658,9 @@ func TestServerPlayTimeout(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -1549,7 +1675,7 @@ func TestServerPlayTimeout(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1570,7 +1696,7 @@ func TestServerPlayWithoutTeardown(t *testing.T) {
|
||||
nconnClosed := make(chan struct{})
|
||||
sessionClosed := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
@@ -1581,10 +1707,10 @@ func TestServerPlayWithoutTeardown(t *testing.T) {
|
||||
onSessionClose: func(ctx *ServerHandlerOnSessionCloseCtx) {
|
||||
close(sessionClosed)
|
||||
},
|
||||
onAnnounce: func(ctx *ServerHandlerOnAnnounceCtx) (*base.Response, error) {
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, nil
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
@@ -1616,6 +1742,9 @@ func TestServerPlayWithoutTeardown(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTH := &headers.Transport{
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
v := headers.TransportDeliveryUnicast
|
||||
@@ -1637,9 +1766,9 @@ func TestServerPlayWithoutTeardown(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -1654,7 +1783,7 @@ func TestServerPlayWithoutTeardown(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1670,11 +1799,16 @@ func TestServerPlayWithoutTeardown(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerPlayUDPChangeConn(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -1708,6 +1842,9 @@ func TestServerPlayUDPChangeConn(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTH := &headers.Transport{
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
v := headers.TransportDeliveryUnicast
|
||||
@@ -1723,9 +1860,9 @@ func TestServerPlayUDPChangeConn(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -1740,7 +1877,7 @@ func TestServerPlayUDPChangeConn(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1760,7 +1897,7 @@ func TestServerPlayUDPChangeConn(t *testing.T) {
|
||||
Method: base.GetParameter,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"4"},
|
||||
"Session": base.HeaderValue{sxID},
|
||||
},
|
||||
})
|
||||
@@ -1770,11 +1907,16 @@ func TestServerPlayUDPChangeConn(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerPlayPartialMedias(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone(), testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media, testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -1804,6 +1946,9 @@ func TestServerPlayPartialMedias(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTH := &headers.Transport{
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
v := headers.TransportDeliveryUnicast
|
||||
@@ -1819,9 +1964,9 @@ func TestServerPlayPartialMedias(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=1"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[1])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -1836,7 +1981,7 @@ func TestServerPlayPartialMedias(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1856,7 +2001,8 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
ssrcs := make([]*uint32, 2)
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTH := &headers.Transport{
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -1873,9 +2019,9 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
},
|
||||
})
|
||||
@@ -1885,6 +2031,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
var th headers.Transport
|
||||
err = th.Unmarshal(res.Header["Transport"])
|
||||
require.NoError(t, err)
|
||||
ssrcs := make([]*uint32, 2)
|
||||
ssrcs[0] = th.SSRC
|
||||
|
||||
inTH = &headers.Transport{
|
||||
@@ -1906,9 +2053,9 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=1"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[1])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Transport": inTH.Marshal(),
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
@@ -1925,7 +2072,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
Method: base.Play,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream"),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"CSeq": base.HeaderValue{"4"},
|
||||
"Session": base.HeaderValue{sx.Session},
|
||||
},
|
||||
})
|
||||
@@ -1946,16 +2093,25 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
err := forma.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
medi := &media.Media{
|
||||
Type: "application",
|
||||
Formats: []format.Format{forma},
|
||||
}
|
||||
|
||||
stream := NewServerStream(media.Medias{medi.Clone(), medi.Clone()})
|
||||
stream := NewServerStream(media.Medias{
|
||||
&media.Media{
|
||||
Type: "application",
|
||||
Formats: []format.Format{forma},
|
||||
},
|
||||
&media.Media{
|
||||
Type: "application",
|
||||
Formats: []format.Format{forma},
|
||||
},
|
||||
})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -1991,7 +2147,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
URL: (&url.URL{
|
||||
Scheme: "rtsp",
|
||||
Host: "localhost:8554",
|
||||
Path: "/teststream/mediaID=0",
|
||||
Path: mustParseURL((*rtpInfo)[0].URL).Path,
|
||||
}).String(),
|
||||
SequenceNumber: func() *uint16 {
|
||||
v := uint16(557)
|
||||
@@ -2025,7 +2181,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
URL: (&url.URL{
|
||||
Scheme: "rtsp",
|
||||
Host: "localhost:8554",
|
||||
Path: "/teststream/mediaID=0",
|
||||
Path: mustParseURL((*rtpInfo)[0].URL).Path,
|
||||
}).String(),
|
||||
SequenceNumber: func() *uint16 {
|
||||
v := uint16(557)
|
||||
@@ -2037,7 +2193,7 @@ func TestServerPlayAdditionalInfos(t *testing.T) {
|
||||
URL: (&url.URL{
|
||||
Scheme: "rtsp",
|
||||
Host: "localhost:8554",
|
||||
Path: "/teststream/mediaID=1",
|
||||
Path: mustParseURL((*rtpInfo)[1].URL).Path,
|
||||
}).String(),
|
||||
SequenceNumber: func() *uint16 {
|
||||
v := uint16(88)
|
||||
|
@@ -30,7 +30,7 @@ func invalidURLAnnounceReq(t *testing.T, control string) base.Request {
|
||||
"Content-Type": base.HeaderValue{"application/sdp"},
|
||||
},
|
||||
Body: func() []byte {
|
||||
medi := testH264Media.Clone()
|
||||
medi := testH264Media
|
||||
medi.Control = control
|
||||
|
||||
sout := &sdp.SessionDescription{
|
||||
@@ -207,7 +207,7 @@ func TestServerRecordSetupPath(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
media := testH264Media.Clone()
|
||||
media := testH264Media
|
||||
media.Control = ca.control
|
||||
|
||||
sout := &sdp.SessionDescription{
|
||||
@@ -298,7 +298,7 @@ func TestServerRecordErrorSetupMediaTwice(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
@@ -315,7 +315,7 @@ func TestServerRecordErrorSetupMediaTwice(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -341,7 +341,7 @@ func TestServerRecordErrorSetupMediaTwice(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -402,7 +402,23 @@ func TestServerRecordErrorRecordPartialMedias(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone(), testH264Media.Clone()}
|
||||
forma := &format.Generic{
|
||||
PayloadTyp: 96,
|
||||
RTPMap: "private/90000",
|
||||
}
|
||||
err = forma.Init()
|
||||
require.NoError(t, err)
|
||||
|
||||
medias := media.Medias{
|
||||
&media.Media{
|
||||
Type: "application",
|
||||
Formats: []format.Format{forma},
|
||||
},
|
||||
&media.Media{
|
||||
Type: "application",
|
||||
Formats: []format.Format{forma},
|
||||
},
|
||||
}
|
||||
medias.SetControls()
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
@@ -432,7 +448,7 @@ func TestServerRecordErrorRecordPartialMedias(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": th.Marshal(),
|
||||
@@ -556,7 +572,26 @@ func TestServerRecord(t *testing.T) {
|
||||
|
||||
<-nconnOpened
|
||||
|
||||
medias := media.Medias{testH264Media.Clone(), testH264Media.Clone()}
|
||||
medias := media.Medias{
|
||||
&media.Media{
|
||||
Type: media.TypeVideo,
|
||||
Formats: []format.Format{&format.H264{
|
||||
PayloadTyp: 96,
|
||||
SPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
PPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
PacketizationMode: 1,
|
||||
}},
|
||||
},
|
||||
&media.Media{
|
||||
Type: media.TypeVideo,
|
||||
Formats: []format.Format{&format.H264{
|
||||
PayloadTyp: 96,
|
||||
SPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
PPS: []byte{0x01, 0x02, 0x03, 0x04},
|
||||
PacketizationMode: 1,
|
||||
}},
|
||||
},
|
||||
}
|
||||
medias.SetControls()
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
@@ -608,7 +643,7 @@ func TestServerRecord(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=" + strconv.FormatInt(int64(i), 10)),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[i].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
@@ -760,7 +795,7 @@ func TestServerRecordErrorInvalidProtocol(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
@@ -790,7 +825,7 @@ func TestServerRecordErrorInvalidProtocol(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
@@ -861,7 +896,7 @@ func TestServerRecordRTCPReport(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
@@ -886,7 +921,7 @@ func TestServerRecordRTCPReport(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -1035,7 +1070,7 @@ func TestServerRecordTimeout(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
@@ -1071,7 +1106,7 @@ func TestServerRecordTimeout(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
@@ -1158,7 +1193,7 @@ func TestServerRecordWithoutTeardown(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
@@ -1194,7 +1229,7 @@ func TestServerRecordWithoutTeardown(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
@@ -1271,7 +1306,7 @@ func TestServerRecordUDPChangeConn(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
medias.SetControls()
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
@@ -1301,7 +1336,7 @@ func TestServerRecordUDPChangeConn(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
@@ -1475,7 +1510,7 @@ func TestServerRecordDecodeErrors(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + medias[0].Control),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": inTH.Marshal(),
|
||||
|
130
server_test.go
130
server_test.go
@@ -315,6 +315,14 @@ type testServerErrMethodNotImplemented struct {
|
||||
stream *ServerStream
|
||||
}
|
||||
|
||||
func (s *testServerErrMethodNotImplemented) OnDescribe(
|
||||
ctx *ServerHandlerOnDescribeCtx,
|
||||
) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, s.stream, nil
|
||||
}
|
||||
|
||||
func (s *testServerErrMethodNotImplemented) OnSetup(
|
||||
ctx *ServerHandlerOnSetupCtx,
|
||||
) (*base.Response, *ServerStream, error) {
|
||||
@@ -326,7 +334,7 @@ func (s *testServerErrMethodNotImplemented) OnSetup(
|
||||
func TestServerErrorMethodNotImplemented(t *testing.T) {
|
||||
for _, ca := range []string{"outside session", "inside session"} {
|
||||
t.Run(ca, func(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
@@ -343,12 +351,15 @@ func TestServerErrorMethodNotImplemented(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
var sx headers.Session
|
||||
|
||||
if ca == "inside session" {
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -380,7 +391,7 @@ func TestServerErrorMethodNotImplemented(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.SetParameter,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: headers,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -395,7 +406,7 @@ func TestServerErrorMethodNotImplemented(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Options,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/"),
|
||||
Header: headers,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -405,11 +416,16 @@ func TestServerErrorMethodNotImplemented(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -438,9 +454,12 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
|
||||
defer nconn1.Close()
|
||||
conn1 := conn.NewConn(nconn1)
|
||||
|
||||
desc1, err := doDescribe(conn1)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn1, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc1.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -480,9 +499,12 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
|
||||
defer nconn2.Close()
|
||||
conn2 := conn.NewConn(nconn2)
|
||||
|
||||
desc2, err := doDescribe(conn2)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err = writeReqReadRes(conn2, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc2.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -505,11 +527,16 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -538,9 +565,12 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -577,7 +607,7 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
|
||||
|
||||
res, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -599,11 +629,16 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerSetupMultipleTransports(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -622,6 +657,9 @@ func TestServerSetupMultipleTransports(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
inTHS := headers.Transports{
|
||||
{
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -651,7 +689,7 @@ func TestServerSetupMultipleTransports(t *testing.T) {
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": inTHS.Marshal(),
|
||||
@@ -676,13 +714,18 @@ func TestServerSetupMultipleTransports(t *testing.T) {
|
||||
func TestServerGetSetParameter(t *testing.T) {
|
||||
for _, ca := range []string{"inside session", "outside session"} {
|
||||
t.Run(ca, func(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
var params []byte
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
ctx.Session.SetUserData(123)
|
||||
return &base.Response{
|
||||
@@ -725,14 +768,17 @@ func TestServerGetSetParameter(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
var sx headers.Session
|
||||
|
||||
if ca == "inside session" {
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"Transport": headers.Transport{
|
||||
Protocol: headers.TransportProtocolTCP,
|
||||
Delivery: func() *headers.TransportDelivery {
|
||||
@@ -755,7 +801,7 @@ func TestServerGetSetParameter(t *testing.T) {
|
||||
}
|
||||
|
||||
headers := base.Header{
|
||||
"CSeq": base.HeaderValue{"2"},
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
}
|
||||
if ca == "inside session" {
|
||||
headers["Session"] = base.HeaderValue{sx.Session}
|
||||
@@ -771,7 +817,7 @@ func TestServerGetSetParameter(t *testing.T) {
|
||||
require.Equal(t, base.StatusOK, res.StatusCode)
|
||||
|
||||
headers = base.Header{
|
||||
"CSeq": base.HeaderValue{"3"},
|
||||
"CSeq": base.HeaderValue{"4"},
|
||||
}
|
||||
if ca == "inside session" {
|
||||
headers["Session"] = base.HeaderValue{sx.Session}
|
||||
@@ -843,7 +889,7 @@ func TestServerErrorInvalidSession(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerSessionClose(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
var session *ServerSession
|
||||
@@ -853,6 +899,11 @@ func TestServerSessionClose(t *testing.T) {
|
||||
onSessionOpen: func(ctx *ServerHandlerOnSessionOpenCtx) {
|
||||
session = ctx.Session
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -871,9 +922,12 @@ func TestServerSessionClose(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -913,7 +967,7 @@ func TestServerSessionAutoClose(t *testing.T) {
|
||||
t.Run(ca, func(t *testing.T) {
|
||||
sessionClosed := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
@@ -921,6 +975,11 @@ func TestServerSessionAutoClose(t *testing.T) {
|
||||
onSessionClose: func(ctx *ServerHandlerOnSessionCloseCtx) {
|
||||
close(sessionClosed)
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
if ca == "200" {
|
||||
return &base.Response{
|
||||
@@ -944,9 +1003,12 @@ func TestServerSessionAutoClose(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -973,11 +1035,16 @@ func TestServerSessionAutoClose(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestServerSessionTeardown(t *testing.T) {
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
Handler: &testServerHandler{
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -996,9 +1063,12 @@ func TestServerSessionTeardown(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -1049,7 +1119,7 @@ func TestServerErrorInvalidPath(t *testing.T) {
|
||||
t.Run(ca, func(t *testing.T) {
|
||||
nconnClosed := make(chan struct{})
|
||||
|
||||
stream := NewServerStream(media.Medias{testH264Media.Clone()})
|
||||
stream := NewServerStream(media.Medias{testH264Media})
|
||||
defer stream.Close()
|
||||
|
||||
s := &Server{
|
||||
@@ -1058,6 +1128,11 @@ func TestServerErrorInvalidPath(t *testing.T) {
|
||||
require.EqualError(t, ctx.Error, "invalid path")
|
||||
close(nconnClosed)
|
||||
},
|
||||
onDescribe: func(ctx *ServerHandlerOnDescribeCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, stream, nil
|
||||
},
|
||||
onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *ServerStream, error) {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
@@ -1076,10 +1151,13 @@ func TestServerErrorInvalidPath(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
desc, err := doDescribe(conn)
|
||||
require.NoError(t, err)
|
||||
|
||||
if ca == "inside session" {
|
||||
res, err := writeReqReadRes(conn, base.Request{
|
||||
Method: base.Setup,
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/mediaID=0"),
|
||||
URL: mustParseURL("rtsp://localhost:8554/teststream/" + controlAttribute(desc.MediaDescriptions[0])),
|
||||
Header: base.Header{
|
||||
"CSeq": base.HeaderValue{"1"},
|
||||
"Transport": headers.Transport{
|
||||
@@ -1163,7 +1241,7 @@ func TestServerAuth(t *testing.T) {
|
||||
defer nconn.Close()
|
||||
conn := conn.NewConn(nconn)
|
||||
|
||||
medias := media.Medias{testH264Media.Clone()}
|
||||
medias := media.Medias{testH264Media}
|
||||
|
||||
req := base.Request{
|
||||
Method: base.Announce,
|
||||
|
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/aler9/gortsplib/v2/pkg/bytecounter"
|
||||
"github.com/aler9/gortsplib/v2/pkg/conn"
|
||||
"github.com/aler9/gortsplib/v2/pkg/liberrors"
|
||||
"github.com/aler9/gortsplib/v2/pkg/media"
|
||||
"github.com/aler9/gortsplib/v2/pkg/url"
|
||||
)
|
||||
|
||||
@@ -377,8 +378,17 @@ func (sc *ServerConn) handleRequest(req *base.Request) (*base.Response, error) {
|
||||
}
|
||||
}
|
||||
|
||||
mediasCopy := make(media.Medias, len(stream.medias))
|
||||
for i, medi := range stream.medias {
|
||||
mediasCopy[i] = &media.Media{
|
||||
Type: medi.Type,
|
||||
Formats: medi.Formats,
|
||||
Control: "mediaUUID=" + stream.streamMedias[medi].uuid.String(),
|
||||
}
|
||||
}
|
||||
|
||||
if stream != nil {
|
||||
byts, _ := stream.Medias().CloneAndSetControls().Marshal(multicast).Marshal()
|
||||
byts, _ := mediasCopy.Marshal(multicast).Marshal()
|
||||
res.Body = byts
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -30,47 +29,52 @@ func stringsReverseIndex(s, substr string) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
func serverParseURLForPlay(u *url.URL) (string, string, int, error) {
|
||||
func serverParseURLForPlay(u *url.URL) (string, string, string, error) {
|
||||
pathAndQuery, ok := u.RTSPPathAndQuery()
|
||||
if !ok {
|
||||
return "", "", -1, liberrors.ErrServerInvalidPath{}
|
||||
return "", "", "", liberrors.ErrServerInvalidPath{}
|
||||
}
|
||||
|
||||
i := stringsReverseIndex(pathAndQuery, "/mediaID=")
|
||||
i := stringsReverseIndex(pathAndQuery, "/mediaUUID=")
|
||||
if i < 0 {
|
||||
if !strings.HasSuffix(pathAndQuery, "/") {
|
||||
return "", "", -1, fmt.Errorf("path of a SETUP request must end with a slash. " +
|
||||
return "", "", "", fmt.Errorf("path of a SETUP request must end with a slash. " +
|
||||
"This typically happens when VLC fails a request, and then switches to an " +
|
||||
"unsupported RTSP dialect")
|
||||
}
|
||||
|
||||
path, query := url.PathSplitQuery(pathAndQuery[:len(pathAndQuery)-1])
|
||||
return path, query, 0, nil
|
||||
return path, query, "", nil
|
||||
}
|
||||
|
||||
var t string
|
||||
pathAndQuery, t = pathAndQuery[:i], pathAndQuery[i+len("/mediaID="):]
|
||||
var mediaUUID string
|
||||
pathAndQuery, mediaUUID = pathAndQuery[:i], pathAndQuery[i+len("/mediaUUID="):]
|
||||
path, query := url.PathSplitQuery(pathAndQuery)
|
||||
tmp, _ := strconv.ParseInt(t, 10, 64)
|
||||
return path, query, int(tmp), nil
|
||||
return path, query, mediaUUID, nil
|
||||
}
|
||||
|
||||
func findMediaByURL(medias media.Medias, baseURL *url.URL, u *url.URL) (*media.Media, bool) {
|
||||
func findMediaByURL(medias media.Medias, baseURL *url.URL, u *url.URL) *media.Media {
|
||||
for _, media := range medias {
|
||||
u1, err := media.URL(baseURL)
|
||||
if err == nil && u1.String() == u.String() {
|
||||
return media, true
|
||||
return media
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
return nil
|
||||
}
|
||||
|
||||
func findMediaByID(medias media.Medias, id int) (*media.Media, bool) {
|
||||
if len(medias) <= id {
|
||||
return nil, false
|
||||
func findMediaByUUID(st *ServerStream, uuid string) *media.Media {
|
||||
if uuid == "" {
|
||||
return st.medias[0]
|
||||
}
|
||||
return medias[id], true
|
||||
|
||||
for _, sm := range st.streamMedias {
|
||||
if sm.uuid.String() == uuid {
|
||||
return sm.media
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func findFirstSupportedTransportHeader(s *Server, tsh headers.Transports) *headers.Transport {
|
||||
@@ -602,11 +606,11 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
|
||||
var path string
|
||||
var query string
|
||||
var mediaID int
|
||||
var mediaUUID string
|
||||
switch ss.state {
|
||||
case ServerSessionStateInitial, ServerSessionStatePrePlay: // play
|
||||
var err error
|
||||
path, query, mediaID, err = serverParseURLForPlay(req.URL)
|
||||
path, query, mediaUUID, err = serverParseURLForPlay(req.URL)
|
||||
if err != nil {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
@@ -686,12 +690,11 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
}
|
||||
|
||||
var medi *media.Media
|
||||
var ok bool
|
||||
switch ss.state {
|
||||
case ServerSessionStateInitial, ServerSessionStatePrePlay: // play
|
||||
medi, ok = findMediaByID(stream.medias, mediaID)
|
||||
medi = findMediaByUUID(stream, mediaUUID)
|
||||
default: // record
|
||||
medi, ok = findMediaByURL(ss.announcedMedias, &url.URL{
|
||||
medi = findMediaByURL(ss.announcedMedias, &url.URL{
|
||||
Scheme: req.URL.Scheme,
|
||||
Host: req.URL.Host,
|
||||
Path: path,
|
||||
@@ -699,7 +702,7 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
}, req.URL)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
if medi == nil {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusBadRequest,
|
||||
}, fmt.Errorf("media not found")
|
||||
@@ -881,15 +884,14 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base
|
||||
var ri headers.RTPInfo
|
||||
now := time.Now()
|
||||
|
||||
for i, sm := range ss.setuppedMediasOrdered {
|
||||
for _, sm := range ss.setuppedMediasOrdered {
|
||||
entry := ss.setuppedStream.rtpInfoEntry(sm.media, now)
|
||||
if entry != nil {
|
||||
entry.URL = (&url.URL{
|
||||
Scheme: req.URL.Scheme,
|
||||
Host: req.URL.Host,
|
||||
Path: "/" + *ss.setuppedPath + "/mediaID=" + strconv.FormatInt(int64(i), 10),
|
||||
Path: "/" + *ss.setuppedPath + "/mediaUUID=" + ss.setuppedStream.streamMedias[sm.media].uuid.String(),
|
||||
}).String()
|
||||
|
||||
ri = append(ri, entry)
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/aler9/gortsplib/v2/pkg/headers"
|
||||
"github.com/aler9/gortsplib/v2/pkg/liberrors"
|
||||
"github.com/aler9/gortsplib/v2/pkg/media"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtcpsender"
|
||||
)
|
||||
|
||||
// ServerStream represents a data stream.
|
||||
@@ -39,27 +38,8 @@ func NewServerStream(medias media.Medias) *ServerStream {
|
||||
}
|
||||
|
||||
st.streamMedias = make(map[*media.Media]*serverStreamMedia, len(medias))
|
||||
for _, media := range medias {
|
||||
ssm := newServerStreamMedia(media)
|
||||
|
||||
ssm.formats = make(map[uint8]*serverStreamFormat)
|
||||
for _, forma := range media.Formats {
|
||||
tr := &serverStreamFormat{
|
||||
format: forma,
|
||||
}
|
||||
|
||||
cmedia := media
|
||||
tr.rtcpSender = rtcpsender.New(
|
||||
forma.ClockRate(),
|
||||
func(pkt rtcp.Packet) {
|
||||
st.WritePacketRTCP(cmedia, pkt)
|
||||
},
|
||||
)
|
||||
|
||||
ssm.formats[forma.PayloadType()] = tr
|
||||
}
|
||||
|
||||
st.streamMedias[media] = ssm
|
||||
for _, medi := range medias {
|
||||
st.streamMedias[medi] = newServerStreamMedia(st, medi)
|
||||
}
|
||||
|
||||
return st
|
||||
@@ -242,8 +222,8 @@ func (st *ServerStream) readerSetActive(ss *ServerSession) {
|
||||
}
|
||||
|
||||
if *ss.setuppedTransport == TransportUDPMulticast {
|
||||
for mediaID, sm := range ss.setuppedMedias {
|
||||
streamMedia := st.streamMedias[mediaID]
|
||||
for medi, sm := range ss.setuppedMedias {
|
||||
streamMedia := st.streamMedias[medi]
|
||||
streamMedia.multicastHandler.rtcpl.addClient(
|
||||
ss.author.ip(), streamMedia.multicastHandler.rtcpl.port(), sm)
|
||||
}
|
||||
@@ -261,8 +241,8 @@ func (st *ServerStream) readerSetInactive(ss *ServerSession) {
|
||||
}
|
||||
|
||||
if *ss.setuppedTransport == TransportUDPMulticast {
|
||||
for mediaID, sm := range ss.setuppedMedias {
|
||||
streamMedia := st.streamMedias[mediaID]
|
||||
for medi, sm := range ss.setuppedMedias {
|
||||
streamMedia := st.streamMedias[medi]
|
||||
streamMedia.multicastHandler.rtcpl.removeClient(sm)
|
||||
}
|
||||
} else {
|
||||
|
@@ -3,22 +3,45 @@ package gortsplib
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pion/rtcp"
|
||||
"github.com/pion/rtp"
|
||||
|
||||
"github.com/aler9/gortsplib/v2/pkg/media"
|
||||
"github.com/aler9/gortsplib/v2/pkg/rtcpsender"
|
||||
)
|
||||
|
||||
type serverStreamMedia struct {
|
||||
uuid uuid.UUID
|
||||
media *media.Media
|
||||
formats map[uint8]*serverStreamFormat
|
||||
multicastHandler *serverMulticastHandler
|
||||
}
|
||||
|
||||
func newServerStreamMedia(medi *media.Media) *serverStreamMedia {
|
||||
return &serverStreamMedia{
|
||||
func newServerStreamMedia(st *ServerStream, medi *media.Media) *serverStreamMedia {
|
||||
sm := &serverStreamMedia{
|
||||
uuid: uuid.New(),
|
||||
media: medi,
|
||||
}
|
||||
|
||||
sm.formats = make(map[uint8]*serverStreamFormat)
|
||||
for _, forma := range medi.Formats {
|
||||
tr := &serverStreamFormat{
|
||||
format: forma,
|
||||
}
|
||||
|
||||
cmedia := medi
|
||||
tr.rtcpSender = rtcpsender.New(
|
||||
forma.ClockRate(),
|
||||
func(pkt rtcp.Packet) {
|
||||
st.WritePacketRTCP(cmedia, pkt)
|
||||
},
|
||||
)
|
||||
|
||||
sm.formats[forma.PayloadType()] = tr
|
||||
}
|
||||
|
||||
return sm
|
||||
}
|
||||
|
||||
func (sm *serverStreamMedia) close() {
|
||||
|
Reference in New Issue
Block a user