rtph264: return error in decoder if packetization-mode is 2 (#153)

This commit is contained in:
Alessandro Ros
2022-11-14 21:23:13 +01:00
committed by GitHub
parent 1161ed966f
commit 51b8063325
19 changed files with 337 additions and 232 deletions

View File

@@ -231,9 +231,10 @@ func TestClientPublishSerial(t *testing.T) {
} }
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
err = c.StartPublishing(scheme+"://localhost:8554/teststream", err = c.StartPublishing(scheme+"://localhost:8554/teststream",
@@ -383,9 +384,10 @@ func TestClientPublishParallel(t *testing.T) {
} }
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
writerDone := make(chan struct{}) writerDone := make(chan struct{})
@@ -542,9 +544,10 @@ func TestClientPublishPauseSerial(t *testing.T) {
} }
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
err = c.StartPublishing("rtsp://localhost:8554/teststream", err = c.StartPublishing("rtsp://localhost:8554/teststream",
@@ -676,9 +679,10 @@ func TestClientPublishPauseParallel(t *testing.T) {
} }
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
err = c.StartPublishing("rtsp://localhost:8554/teststream", err = c.StartPublishing("rtsp://localhost:8554/teststream",
@@ -817,9 +821,10 @@ func TestClientPublishAutomaticProtocol(t *testing.T) {
}() }()
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
c := Client{} c := Client{}
@@ -981,9 +986,10 @@ func TestClientPublishRTCPReport(t *testing.T) {
err = c.StartPublishing("rtsp://localhost:8554/teststream", err = c.StartPublishing("rtsp://localhost:8554/teststream",
Tracks{&TrackH264{ Tracks{&TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}}) }})
require.NoError(t, err) require.NoError(t, err)
defer c.Close() defer c.Close()
@@ -1117,9 +1123,10 @@ func TestClientPublishIgnoreTCPRTPPackets(t *testing.T) {
} }
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
err = c.StartPublishing("rtsp://localhost:8554/teststream", err = c.StartPublishing("rtsp://localhost:8554/teststream",

View File

@@ -51,9 +51,10 @@ func startReading(c *Client, ur string) error {
func TestClientReadTracks(t *testing.T) { func TestClientReadTracks(t *testing.T) {
track1 := &TrackH264{ track1 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
track2 := &TrackMPEG4Audio{ track2 := &TrackMPEG4Audio{
@@ -498,15 +499,17 @@ func TestClientReadPartial(t *testing.T) {
require.Equal(t, mustParseURL("rtsp://"+listenIP+":8554/teststream"), req.URL) require.Equal(t, mustParseURL("rtsp://"+listenIP+":8554/teststream"), req.URL)
track1 := &TrackH264{ track1 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
track2 := &TrackH264{ track2 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track1, track2} tracks := Tracks{track1, track2}
@@ -651,9 +654,10 @@ func TestClientReadContentBase(t *testing.T) {
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL) require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -787,9 +791,10 @@ func TestClientReadAnyPort(t *testing.T) {
require.Equal(t, base.Describe, req.Method) require.Equal(t, base.Describe, req.Method)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -945,9 +950,10 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
require.Equal(t, base.Describe, req.Method) require.Equal(t, base.Describe, req.Method)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -1038,9 +1044,10 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
defer close(serverDone) defer close(serverDone)
tracks := Tracks{&TrackH264{ tracks := Tracks{&TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}} }}
tracks.setControls() tracks.setControls()
@@ -1302,9 +1309,10 @@ func TestClientReadDifferentInterleavedIDs(t *testing.T) {
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL) require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
track1 := &TrackH264{ track1 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track1} tracks := Tracks{track1}
@@ -1512,9 +1520,10 @@ func TestClientReadRedirect(t *testing.T) {
} }
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -1672,9 +1681,10 @@ func TestClientReadPause(t *testing.T) {
require.Equal(t, base.Describe, req.Method) require.Equal(t, base.Describe, req.Method)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -1846,9 +1856,10 @@ func TestClientReadRTCPReport(t *testing.T) {
require.Equal(t, base.Describe, req.Method) require.Equal(t, base.Describe, req.Method)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -2027,9 +2038,10 @@ func TestClientReadErrorTimeout(t *testing.T) {
require.Equal(t, base.Describe, req.Method) require.Equal(t, base.Describe, req.Method)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -2179,9 +2191,10 @@ func TestClientReadIgnoreTCPInvalidTrack(t *testing.T) {
require.Equal(t, base.Describe, req.Method) require.Equal(t, base.Describe, req.Method)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -2308,9 +2321,10 @@ func TestClientReadSeek(t *testing.T) {
require.Equal(t, base.Describe, req.Method) require.Equal(t, base.Describe, req.Method)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -2480,9 +2494,10 @@ func TestClientReadKeepaliveFromSession(t *testing.T) {
require.Equal(t, base.Describe, req.Method) require.Equal(t, base.Describe, req.Method)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -2609,9 +2624,10 @@ func TestClientReadDifferentSource(t *testing.T) {
require.Equal(t, mustParseURL("rtsp://localhost:8554/test/stream?param=value"), req.URL) require.Equal(t, mustParseURL("rtsp://localhost:8554/test/stream?param=value"), req.URL)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}

View File

@@ -106,9 +106,10 @@ func TestClientSession(t *testing.T) {
require.Equal(t, base.HeaderValue{"123456"}, req.Header["Session"]) require.Equal(t, base.HeaderValue{"123456"}, req.Header["Session"])
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -189,9 +190,10 @@ func TestClientAuth(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -255,9 +257,10 @@ func TestClientDescribeCharset(t *testing.T) {
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL) require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
track1 := &TrackH264{ track1 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
err = conn.WriteResponse(&base.Response{ err = conn.WriteResponse(&base.Response{

View File

@@ -36,7 +36,8 @@ func main() {
// create an H264 track // create an H264 track
track := &gortsplib.TrackH264{ track := &gortsplib.TrackH264{
PayloadType: 96, PayloadType: 96,
PacketizationMode: 1,
} }
// connect to the server and start publishing the track // connect to the server and start publishing the track

View File

@@ -37,7 +37,8 @@ func main() {
// create an H264 track // create an H264 track
track := &gortsplib.TrackH264{ track := &gortsplib.TrackH264{
PayloadType: 96, PayloadType: 96,
PacketizationMode: 1,
} }
// Client allows to set additional client options // Client allows to set additional client options

View File

@@ -38,7 +38,8 @@ func main() {
// create an H264 track // create an H264 track
track := &gortsplib.TrackH264{ track := &gortsplib.TrackH264{
PayloadType: 96, PayloadType: 96,
PacketizationMode: 1,
} }
// connect to the server and start publishing the track // connect to the server and start publishing the track

View File

@@ -62,20 +62,22 @@ func main() {
} }
// find the H264 track // find the H264 track
h264track := func() *gortsplib.TrackH264 { track := func() *gortsplib.TrackH264 {
for _, track := range tracks { for _, track := range tracks {
if h264track, ok := track.(*gortsplib.TrackH264); ok { if track, ok := track.(*gortsplib.TrackH264); ok {
return h264track return track
} }
} }
return nil return nil
}() }()
if h264track == nil { if track == nil {
panic("H264 track not found") panic("H264 track not found")
} }
// setup RTP/H264->H264 decoder // setup RTP/H264->H264 decoder
rtpDec := &rtph264.Decoder{} rtpDec := &rtph264.Decoder{
PacketizationMode: track.PacketizationMode,
}
rtpDec.Init() rtpDec.Init()
// setup H264->raw frames decoder // setup H264->raw frames decoder
@@ -86,11 +88,11 @@ func main() {
defer h264RawDec.close() defer h264RawDec.close()
// if SPS and PPS are present into the SDP, send them to the decoder // if SPS and PPS are present into the SDP, send them to the decoder
sps := h264track.SafeSPS() sps := track.SafeSPS()
if sps != nil { if sps != nil {
h264RawDec.decode(sps) h264RawDec.decode(sps)
} }
pps := h264track.SafePPS() pps := track.SafePPS()
if pps != nil { if pps != nil {
h264RawDec.decode(pps) h264RawDec.decode(pps)
} }
@@ -131,7 +133,7 @@ func main() {
} }
// setup and read the H264 track only // setup and read the H264 track only
err = c.SetupAndPlay(gortsplib.Tracks{h264track}, baseURL) err = c.SetupAndPlay(gortsplib.Tracks{track}, baseURL)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@@ -47,7 +47,9 @@ func main() {
} }
// setup RTP/H264->H264 decoder // setup RTP/H264->H264 decoder
rtpDec := &rtph264.Decoder{} rtpDec := &rtph264.Decoder{
PacketizationMode: track.PacketizationMode,
}
rtpDec.Init() rtpDec.Init()
// setup H264->MPEGTS muxer // setup H264->MPEGTS muxer

View File

@@ -52,7 +52,9 @@ func main() {
} }
// setup RTP/H264->H264 decoder // setup RTP/H264->H264 decoder
rtpDec := &rtph264.Decoder{} rtpDec := &rtph264.Decoder{
PacketizationMode: track.PacketizationMode,
}
rtpDec.Init() rtpDec.Init()
// setup H264->raw frames decoder // setup H264->raw frames decoder

View File

@@ -79,7 +79,9 @@ func (sh *serverHandler) OnAnnounce(ctx *gortsplib.ServerHandlerOnAnnounceCtx) (
} }
// setup RTP/H264->H264 decoder // setup RTP/H264->H264 decoder
rtpDec := &rtph264.Decoder{} rtpDec := &rtph264.Decoder{
PacketizationMode: h264track.PacketizationMode,
}
rtpDec.Init() rtpDec.Init()
// setup H264->MPEGTS muxer // setup H264->MPEGTS muxer

View File

@@ -24,6 +24,9 @@ var ErrNonStartingPacketAndNoPrevious = errors.New(
// Decoder is a RTP/H264 decoder. // Decoder is a RTP/H264 decoder.
type Decoder struct { type Decoder struct {
// indicates the packetization mode.
PacketizationMode int
timeDecoder *rtptimedec.Decoder timeDecoder *rtptimedec.Decoder
firstPacketReceived bool firstPacketReceived bool
fragmentedSize int fragmentedSize int
@@ -42,6 +45,10 @@ func (d *Decoder) Init() {
// Decode decodes NALUs from a RTP/H264 packet. // Decode decodes NALUs from a RTP/H264 packet.
func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
if d.PacketizationMode >= 2 {
return nil, 0, fmt.Errorf("PacketizationMode >= 2 is not supported")
}
if len(pkt.Payload) < 1 { if len(pkt.Payload) < 1 {
d.fragments = d.fragments[:0] // discard pending fragmented packets d.fragments = d.fragments[:0] // discard pending fragmented packets
return nil, 0, fmt.Errorf("payload is too short") return nil, 0, fmt.Errorf("payload is too short")
@@ -154,7 +161,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) {
return nil, 0, err return nil, 0, err
} }
return nalus, d.timeDecoder.Decode(pkt.Timestamp), err return nalus, d.timeDecoder.Decode(pkt.Timestamp), nil
} }
// DecodeUntilMarker decodes NALUs from a RTP/H264 packet and puts them in a buffer. // DecodeUntilMarker decodes NALUs from a RTP/H264 packet and puts them in a buffer.

View File

@@ -2,5 +2,5 @@
package rtph264 package rtph264
const ( const (
rtpClockRate = 90000 // h264 always uses 90khz rtpClockRate = 90000 // H264 always uses 90khz
) )

View File

@@ -27,9 +27,10 @@ func invalidURLAnnounceReq(t *testing.T, control string) base.Request {
}, },
Body: func() []byte { Body: func() []byte {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
track.SetControl(control) track.SetControl(control)
@@ -232,9 +233,10 @@ func TestServerPublishSetupPath(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
track.SetControl(ca.control) track.SetControl(ca.control)
@@ -327,9 +329,10 @@ func TestServerPublishErrorSetupDifferentPaths(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -407,9 +410,10 @@ func TestServerPublishErrorSetupTrackTwice(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -508,15 +512,17 @@ func TestServerPublishErrorRecordPartialTracks(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track1 := &TrackH264{ track1 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
track2 := &TrackH264{ track2 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track1, track2} tracks := Tracks{track1, track2}
@@ -665,9 +671,10 @@ func TestServerPublish(t *testing.T) {
<-nconnOpened <-nconnOpened
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -861,9 +868,10 @@ func TestServerPublishErrorInvalidProtocol(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -966,9 +974,10 @@ func TestServerPublishRTCPReport(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -1143,9 +1152,10 @@ func TestServerPublishTimeout(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -1272,9 +1282,10 @@ func TestServerPublishWithoutTeardown(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}
@@ -1391,9 +1402,10 @@ func TestServerPublishUDPChangeConn(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
tracks := Tracks{track} tracks := Tracks{track}

View File

@@ -93,9 +93,10 @@ func TestServerReadSetupPath(t *testing.T) {
} { } {
t.Run(ca.name, func(t *testing.T) { t.Run(ca.name, func(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track, track, track, track, track}) stream := NewServerStream(Tracks{track, track, track, track, track})
@@ -160,9 +161,10 @@ func TestServerReadSetupErrors(t *testing.T) {
nconnClosed := make(chan struct{}) nconnClosed := make(chan struct{})
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -282,9 +284,10 @@ func TestServerReadSetupErrors(t *testing.T) {
func TestServerReadSetupErrorSameUDPPortsAndIP(t *testing.T) { func TestServerReadSetupErrorSameUDPPortsAndIP(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -375,9 +378,10 @@ func TestServerRead(t *testing.T) {
framesReceived := make(chan struct{}) framesReceived := make(chan struct{})
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -716,9 +720,10 @@ func TestServerReadRTCPReport(t *testing.T) {
for _, ca := range []string{"udp", "tcp"} { for _, ca := range []string{"udp", "tcp"} {
t.Run(ca, func(t *testing.T) { t.Run(ca, func(t *testing.T) {
stream := NewServerStream(Tracks{&TrackH264{ stream := NewServerStream(Tracks{&TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}}) }})
defer stream.Close() defer stream.Close()
@@ -864,9 +869,10 @@ func TestServerReadRTCPReport(t *testing.T) {
func TestServerReadVLCMulticast(t *testing.T) { func TestServerReadVLCMulticast(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -919,9 +925,10 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) {
writerTerminate := make(chan struct{}) writerTerminate := make(chan struct{})
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -1019,9 +1026,10 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) {
func TestServerReadPlayPlay(t *testing.T) { func TestServerReadPlayPlay(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -1109,9 +1117,10 @@ func TestServerReadPlayPausePlay(t *testing.T) {
writerTerminate := make(chan struct{}) writerTerminate := make(chan struct{})
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -1235,9 +1244,10 @@ func TestServerReadPlayPausePause(t *testing.T) {
writerTerminate := make(chan struct{}) writerTerminate := make(chan struct{})
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -1369,9 +1379,10 @@ func TestServerReadTimeout(t *testing.T) {
sessionClosed := make(chan struct{}) sessionClosed := make(chan struct{})
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -1484,9 +1495,10 @@ func TestServerReadWithoutTeardown(t *testing.T) {
sessionClosed := make(chan struct{}) sessionClosed := make(chan struct{})
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -1590,9 +1602,10 @@ func TestServerReadWithoutTeardown(t *testing.T) {
func TestServerReadUDPChangeConn(t *testing.T) { func TestServerReadUDPChangeConn(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -1696,15 +1709,17 @@ func TestServerReadUDPChangeConn(t *testing.T) {
func TestServerReadPartialTracks(t *testing.T) { func TestServerReadPartialTracks(t *testing.T) {
track1 := &TrackH264{ track1 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
track2 := &TrackH264{ track2 := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track1, track2}) stream := NewServerStream(Tracks{track1, track2})

View File

@@ -340,9 +340,10 @@ func TestServerErrorMethodNotImplemented(t *testing.T) {
for _, ca := range []string{"outside session", "inside session"} { for _, ca := range []string{"outside session", "inside session"} {
t.Run(ca, func(t *testing.T) { t.Run(ca, func(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -425,9 +426,10 @@ func TestServerErrorMethodNotImplemented(t *testing.T) {
func TestServerErrorTCPTwoConnOneSession(t *testing.T) { func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -531,9 +533,10 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) {
func TestServerErrorTCPOneConnTwoSessions(t *testing.T) { func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -631,9 +634,10 @@ func TestServerErrorTCPOneConnTwoSessions(t *testing.T) {
func TestServerSetupMultipleTransports(t *testing.T) { func TestServerSetupMultipleTransports(t *testing.T) {
stream := NewServerStream(Tracks{&TrackH264{ stream := NewServerStream(Tracks{&TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}}) }})
defer stream.Close() defer stream.Close()
@@ -712,9 +716,10 @@ func TestServerGetSetParameter(t *testing.T) {
for _, ca := range []string{"inside session", "outside session"} { for _, ca := range []string{"inside session", "outside session"} {
t.Run(ca, func(t *testing.T) { t.Run(ca, func(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -885,9 +890,10 @@ func TestServerErrorInvalidSession(t *testing.T) {
func TestServerSessionClose(t *testing.T) { func TestServerSessionClose(t *testing.T) {
stream := NewServerStream(Tracks{&TrackH264{ stream := NewServerStream(Tracks{&TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}}) }})
defer stream.Close() defer stream.Close()
@@ -959,9 +965,10 @@ func TestServerSessionAutoClose(t *testing.T) {
sessionClosed := make(chan struct{}) sessionClosed := make(chan struct{})
stream := NewServerStream(Tracks{&TrackH264{ stream := NewServerStream(Tracks{&TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}}) }})
defer stream.Close() defer stream.Close()
@@ -1023,9 +1030,10 @@ func TestServerSessionAutoClose(t *testing.T) {
func TestServerSessionTeardown(t *testing.T) { func TestServerSessionTeardown(t *testing.T) {
stream := NewServerStream(Tracks{&TrackH264{ stream := NewServerStream(Tracks{&TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}}) }})
defer stream.Close() defer stream.Close()
@@ -1103,9 +1111,10 @@ func TestServerErrorInvalidPath(t *testing.T) {
nconnClosed := make(chan struct{}) nconnClosed := make(chan struct{})
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
stream := NewServerStream(Tracks{track}) stream := NewServerStream(Tracks{track})
@@ -1223,9 +1232,10 @@ func TestServerAuth(t *testing.T) {
conn := conn.NewConn(nconn) conn := conn.NewConn(nconn)
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04}, SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
} }
req := base.Request{ req := base.Request{

View File

@@ -13,9 +13,10 @@ import (
// TrackH264 is a H264 track. // TrackH264 is a H264 track.
type TrackH264 struct { type TrackH264 struct {
PayloadType uint8 PayloadType uint8
SPS []byte SPS []byte
PPS []byte PPS []byte
PacketizationMode int
trackBase trackBase
mutex sync.RWMutex mutex sync.RWMutex
@@ -61,7 +62,8 @@ func (t *TrackH264) fillParamsFromMediaDescription(md *psdp.MediaDescription) er
return fmt.Errorf("invalid fmtp attribute (%v)", v) return fmt.Errorf("invalid fmtp attribute (%v)", v)
} }
if tmp[0] == "sprop-parameter-sets" { switch tmp[0] {
case "sprop-parameter-sets":
tmp := strings.Split(tmp[1], ",") tmp := strings.Split(tmp[1], ",")
if len(tmp) < 2 { if len(tmp) < 2 {
return fmt.Errorf("invalid sprop-parameter-sets (%v)", v) return fmt.Errorf("invalid sprop-parameter-sets (%v)", v)
@@ -79,7 +81,14 @@ func (t *TrackH264) fillParamsFromMediaDescription(md *psdp.MediaDescription) er
t.SPS = sps t.SPS = sps
t.PPS = pps t.PPS = pps
return nil
case "packetization-mode":
tmp, err := strconv.ParseInt(tmp[1], 10, 64)
if err != nil {
return fmt.Errorf("invalid packetization-mode (%v)", v)
}
t.PacketizationMode = int(tmp)
} }
} }
@@ -93,10 +102,11 @@ func (t *TrackH264) ClockRate() int {
func (t *TrackH264) clone() Track { func (t *TrackH264) clone() Track {
return &TrackH264{ return &TrackH264{
PayloadType: t.PayloadType, PayloadType: t.PayloadType,
SPS: t.SPS, SPS: t.SPS,
PPS: t.PPS, PPS: t.PPS,
trackBase: t.trackBase, PacketizationMode: t.PacketizationMode,
trackBase: t.trackBase,
} }
} }
@@ -135,21 +145,27 @@ func (t *TrackH264) MediaDescription() *psdp.MediaDescription {
typ := strconv.FormatInt(int64(t.PayloadType), 10) typ := strconv.FormatInt(int64(t.PayloadType), 10)
fmtp := typ + " packetization-mode=1" fmtp := typ
var tmp []string var tmp []string
if t.PacketizationMode != 0 {
tmp = append(tmp, "packetization-mode="+strconv.FormatInt(int64(t.PacketizationMode), 10))
}
var tmp2 []string
if t.SPS != nil { if t.SPS != nil {
tmp = append(tmp, base64.StdEncoding.EncodeToString(t.SPS)) tmp2 = append(tmp2, base64.StdEncoding.EncodeToString(t.SPS))
} }
if t.PPS != nil { if t.PPS != nil {
tmp = append(tmp, base64.StdEncoding.EncodeToString(t.PPS)) tmp2 = append(tmp2, base64.StdEncoding.EncodeToString(t.PPS))
} }
if len(tmp) > 0 { if tmp2 != nil {
fmtp += "; sprop-parameter-sets=" + strings.Join(tmp, ",") tmp = append(tmp, "sprop-parameter-sets="+strings.Join(tmp2, ","))
} }
if len(t.SPS) >= 4 { if len(t.SPS) >= 4 {
fmtp += "; profile-level-id=" + strings.ToUpper(hex.EncodeToString(t.SPS[1:4])) tmp = append(tmp, "profile-level-id="+strings.ToUpper(hex.EncodeToString(t.SPS[1:4])))
}
if tmp != nil {
fmtp += " " + strings.Join(tmp, "; ")
} }
return &psdp.MediaDescription{ return &psdp.MediaDescription{

View File

@@ -9,9 +9,10 @@ import (
func TestTrackH264Attributes(t *testing.T) { func TestTrackH264Attributes(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02}, SPS: []byte{0x01, 0x02},
PPS: []byte{0x03, 0x04}, PPS: []byte{0x03, 0x04},
PacketizationMode: 1,
} }
require.Equal(t, 90000, track.ClockRate()) require.Equal(t, 90000, track.ClockRate())
require.Equal(t, "", track.GetControl()) require.Equal(t, "", track.GetControl())
@@ -175,7 +176,7 @@ func TestTrackH264GetSPSPPSErrors(t *testing.T) {
}, },
} { } {
t.Run(ca.name, func(t *testing.T) { t.Run(ca.name, func(t *testing.T) {
tr := &TrackH264{} var tr TrackH264
err := tr.fillParamsFromMediaDescription(ca.md) err := tr.fillParamsFromMediaDescription(ca.md)
require.EqualError(t, err, ca.err) require.EqualError(t, err, ca.err)
}) })
@@ -184,9 +185,10 @@ func TestTrackH264GetSPSPPSErrors(t *testing.T) {
func TestTrackH264Clone(t *testing.T) { func TestTrackH264Clone(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
SPS: []byte{0x01, 0x02}, SPS: []byte{0x01, 0x02},
PPS: []byte{0x03, 0x04}, PPS: []byte{0x03, 0x04},
PacketizationMode: 1,
} }
clone := track.clone() clone := track.clone()
@@ -206,6 +208,7 @@ func TestTrackH264MediaDescription(t *testing.T) {
PPS: []byte{ PPS: []byte{
0x68, 0xee, 0x3c, 0x80, 0x68, 0xee, 0x3c, 0x80,
}, },
PacketizationMode: 1,
} }
require.Equal(t, &psdp.MediaDescription{ require.Equal(t, &psdp.MediaDescription{
@@ -234,7 +237,8 @@ func TestTrackH264MediaDescription(t *testing.T) {
t.Run("no sps/pps", func(t *testing.T) { t.Run("no sps/pps", func(t *testing.T) {
track := &TrackH264{ track := &TrackH264{
PayloadType: 96, PayloadType: 96,
PacketizationMode: 1,
} }
require.Equal(t, &psdp.MediaDescription{ require.Equal(t, &psdp.MediaDescription{

View File

@@ -258,6 +258,7 @@ func TestTrackNewFromMediaDescription(t *testing.T) {
PPS: []byte{ PPS: []byte{
0x68, 0xee, 0x3c, 0x80, 0x68, 0xee, 0x3c, 0x80,
}, },
PacketizationMode: 1,
}, },
}, },
{ {
@@ -310,6 +311,7 @@ func TestTrackNewFromMediaDescription(t *testing.T) {
PPS: []byte{ PPS: []byte{
0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0,
}, },
PacketizationMode: 1,
}, },
}, },
{ {
@@ -343,6 +345,7 @@ func TestTrackNewFromMediaDescription(t *testing.T) {
PPS: []byte{ PPS: []byte{
0x68, 0xfa, 0x8f, 0x2c, 0x68, 0xfa, 0x8f, 0x2c,
}, },
PacketizationMode: 1,
}, },
}, },
{ {

View File

@@ -76,9 +76,10 @@ func TestTracksReadSkipGenericTracksWithoutClockRate(t *testing.T) {
trackBase: trackBase{ trackBase: trackBase{
control: "rtsp://10.0.100.50/profile5/media.smp/trackID=v", control: "rtsp://10.0.100.50/profile5/media.smp/trackID=v",
}, },
PayloadType: 97, PayloadType: 97,
SPS: []byte{0x67, 0x64, 0x00, 0x28, 0xac, 0xb4, 0x03, 0xc0, 0x11, 0x3f, 0x2a}, SPS: []byte{0x67, 0x64, 0x00, 0x28, 0xac, 0xb4, 0x03, 0xc0, 0x11, 0x3f, 0x2a},
PPS: []byte{0x68, 0xee, 0x01, 0x9e, 0x2c}, PPS: []byte{0x68, 0xee, 0x01, 0x9e, 0x2c},
PacketizationMode: 1,
}, },
&TrackPCMU{ &TrackPCMU{
trackBase: trackBase{ trackBase: trackBase{