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{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
err = c.StartPublishing(scheme+"://localhost:8554/teststream",
@@ -383,9 +384,10 @@ func TestClientPublishParallel(t *testing.T) {
}
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
writerDone := make(chan struct{})
@@ -542,9 +544,10 @@ func TestClientPublishPauseSerial(t *testing.T) {
}
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
err = c.StartPublishing("rtsp://localhost:8554/teststream",
@@ -676,9 +679,10 @@ func TestClientPublishPauseParallel(t *testing.T) {
}
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
err = c.StartPublishing("rtsp://localhost:8554/teststream",
@@ -817,9 +821,10 @@ func TestClientPublishAutomaticProtocol(t *testing.T) {
}()
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
c := Client{}
@@ -981,9 +986,10 @@ func TestClientPublishRTCPReport(t *testing.T) {
err = c.StartPublishing("rtsp://localhost:8554/teststream",
Tracks{&TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}})
require.NoError(t, err)
defer c.Close()
@@ -1117,9 +1123,10 @@ func TestClientPublishIgnoreTCPRTPPackets(t *testing.T) {
}
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
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) {
track1 := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
track2 := &TrackMPEG4Audio{
@@ -498,15 +499,17 @@ func TestClientReadPartial(t *testing.T) {
require.Equal(t, mustParseURL("rtsp://"+listenIP+":8554/teststream"), req.URL)
track1 := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
track2 := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track1, track2}
@@ -651,9 +654,10 @@ func TestClientReadContentBase(t *testing.T) {
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -787,9 +791,10 @@ func TestClientReadAnyPort(t *testing.T) {
require.Equal(t, base.Describe, req.Method)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -945,9 +950,10 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
require.Equal(t, base.Describe, req.Method)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -1038,9 +1044,10 @@ func TestClientReadAutomaticProtocol(t *testing.T) {
defer close(serverDone)
tracks := Tracks{&TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}}
tracks.setControls()
@@ -1302,9 +1309,10 @@ func TestClientReadDifferentInterleavedIDs(t *testing.T) {
require.Equal(t, mustParseURL("rtsp://localhost:8554/teststream"), req.URL)
track1 := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track1}
@@ -1512,9 +1520,10 @@ func TestClientReadRedirect(t *testing.T) {
}
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -1672,9 +1681,10 @@ func TestClientReadPause(t *testing.T) {
require.Equal(t, base.Describe, req.Method)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -1846,9 +1856,10 @@ func TestClientReadRTCPReport(t *testing.T) {
require.Equal(t, base.Describe, req.Method)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -2027,9 +2038,10 @@ func TestClientReadErrorTimeout(t *testing.T) {
require.Equal(t, base.Describe, req.Method)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -2179,9 +2191,10 @@ func TestClientReadIgnoreTCPInvalidTrack(t *testing.T) {
require.Equal(t, base.Describe, req.Method)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -2308,9 +2321,10 @@ func TestClientReadSeek(t *testing.T) {
require.Equal(t, base.Describe, req.Method)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}
@@ -2480,9 +2494,10 @@ func TestClientReadKeepaliveFromSession(t *testing.T) {
require.Equal(t, base.Describe, req.Method)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
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)
track := &TrackH264{
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PayloadType: 96,
SPS: []byte{0x01, 0x02, 0x03, 0x04},
PPS: []byte{0x01, 0x02, 0x03, 0x04},
PacketizationMode: 1,
}
tracks := Tracks{track}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -24,6 +24,9 @@ var ErrNonStartingPacketAndNoPrevious = errors.New(
// Decoder is a RTP/H264 decoder.
type Decoder struct {
// indicates the packetization mode.
PacketizationMode int
timeDecoder *rtptimedec.Decoder
firstPacketReceived bool
fragmentedSize int
@@ -42,6 +45,10 @@ func (d *Decoder) Init() {
// Decode decodes NALUs from a RTP/H264 packet.
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 {
d.fragments = d.fragments[:0] // discard pending fragmented packets
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 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.

View File

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

View File

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

View File

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

View File

@@ -13,9 +13,10 @@ import (
// TrackH264 is a H264 track.
type TrackH264 struct {
PayloadType uint8
SPS []byte
PPS []byte
PayloadType uint8
SPS []byte
PPS []byte
PacketizationMode int
trackBase
mutex sync.RWMutex
@@ -61,7 +62,8 @@ func (t *TrackH264) fillParamsFromMediaDescription(md *psdp.MediaDescription) er
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], ",")
if len(tmp) < 2 {
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.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 {
return &TrackH264{
PayloadType: t.PayloadType,
SPS: t.SPS,
PPS: t.PPS,
trackBase: t.trackBase,
PayloadType: t.PayloadType,
SPS: t.SPS,
PPS: t.PPS,
PacketizationMode: t.PacketizationMode,
trackBase: t.trackBase,
}
}
@@ -135,21 +145,27 @@ func (t *TrackH264) MediaDescription() *psdp.MediaDescription {
typ := strconv.FormatInt(int64(t.PayloadType), 10)
fmtp := typ + " packetization-mode=1"
fmtp := typ
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 {
tmp = append(tmp, base64.StdEncoding.EncodeToString(t.SPS))
tmp2 = append(tmp2, base64.StdEncoding.EncodeToString(t.SPS))
}
if t.PPS != nil {
tmp = append(tmp, base64.StdEncoding.EncodeToString(t.PPS))
tmp2 = append(tmp2, base64.StdEncoding.EncodeToString(t.PPS))
}
if len(tmp) > 0 {
fmtp += "; sprop-parameter-sets=" + strings.Join(tmp, ",")
if tmp2 != nil {
tmp = append(tmp, "sprop-parameter-sets="+strings.Join(tmp2, ","))
}
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{

View File

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

View File

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

View File

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