1
0
Fork 0
forked from External/mediamtx

update gortsplib

This commit is contained in:
aler9 2022-01-30 17:36:42 +01:00
parent 9bc364fa21
commit 2bfdcc7d89
23 changed files with 235 additions and 280 deletions

View file

@ -186,7 +186,7 @@ func TestAPIPathsList(t *testing.T) {
require.Equal(t, true, ok)
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
func() {
@ -251,7 +251,7 @@ func TestAPIList(t *testing.T) {
defer p.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
switch ca {
@ -382,7 +382,7 @@ func TestAPIKick(t *testing.T) {
defer p.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
switch ca {

View file

@ -1,8 +1,11 @@
package core
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
"path/filepath"
@ -12,7 +15,7 @@ import (
"github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/base"
psdp "github.com/pion/sdp/v3"
"github.com/aler9/gortsplib/pkg/headers"
"github.com/stretchr/testify/require"
)
@ -160,33 +163,61 @@ func TestCorePathAutoDeletion(t *testing.T) {
defer p.close()
func() {
c := gortsplib.Client{}
err := c.Start("rtsp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer c.Close()
defer conn.Close()
br := bufio.NewReader(conn)
if ca == "describe" {
ur, err := base.ParseURL("rtsp://localhost:8554/mypath")
u, err := base.ParseURL("rtsp://localhost:8554/mypath")
require.NoError(t, err)
_, _, _, err = c.Describe(ur)
require.EqualError(t, err, "bad status code: 404 (Not Found)")
var bb bytes.Buffer
base.Request{
Method: base.Describe,
URL: u,
Header: base.Header{
"CSeq": base.HeaderValue{"1"},
},
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
var res base.Response
err = res.Read(br)
require.NoError(t, err)
require.Equal(t, base.StatusNotFound, res.StatusCode)
} else {
baseURL, err := base.ParseURL("rtsp://localhost:8554/mypath/")
u, err := base.ParseURL("rtsp://localhost:8554/mypath/trackID=0")
require.NoError(t, err)
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
var bb bytes.Buffer
base.Request{
Method: base.Setup,
URL: u,
Header: base.Header{
"CSeq": base.HeaderValue{"1"},
"Transport": headers.Transport{
Mode: func() *headers.TransportMode {
v := headers.TransportModePlay
return &v
}(),
Delivery: func() *headers.TransportDelivery {
v := headers.TransportDeliveryUnicast
return &v
}(),
Protocol: headers.TransportProtocolUDP,
ClientPorts: &[2]int{35466, 35467},
}.Write(),
},
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
Key: "control",
Value: "trackID=0",
})
_, err = c.Setup(true, track, baseURL, 0, 0)
require.EqualError(t, err, "bad status code: 404 (Not Found)")
var res base.Response
err = res.Read(br)
require.NoError(t, err)
require.Equal(t, base.StatusNotFound, res.StatusCode)
}
}()
@ -219,7 +250,7 @@ func main() {
}
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
if err != nil {
panic(err)
}
@ -270,35 +301,59 @@ func main() {
defer p1.close()
func() {
c := gortsplib.Client{}
err := c.Start("rtsp", "localhost:8554")
conn, err := net.Dial("tcp", "localhost:8554")
require.NoError(t, err)
defer c.Close()
defer conn.Close()
br := bufio.NewReader(conn)
if ca == "describe" || ca == "describe and setup" {
ur, err := base.ParseURL("rtsp://localhost:8554/ondemand")
u, err := base.ParseURL("rtsp://localhost:8554/ondemand")
require.NoError(t, err)
_, _, _, err = c.Describe(ur)
var bb bytes.Buffer
base.Request{
Method: base.Describe,
URL: u,
Header: base.Header{
"CSeq": base.HeaderValue{"1"},
},
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
var res base.Response
err = res.Read(br)
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
}
if ca == "setup" || ca == "describe and setup" {
baseURL, err := base.ParseURL("rtsp://localhost:8554/ondemand/")
u, err := base.ParseURL("rtsp://localhost:8554/ondemand/trackID=0")
require.NoError(t, err)
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
var bb bytes.Buffer
base.Request{
Method: base.Setup,
URL: u,
Header: base.Header{
"CSeq": base.HeaderValue{"2"},
"Transport": headers.Transport{
Mode: func() *headers.TransportMode {
v := headers.TransportModePlay
return &v
}(),
Protocol: headers.TransportProtocolTCP,
InterleavedIDs: &[2]int{0, 1},
}.Write(),
},
}.Write(&bb)
_, err = conn.Write(bb.Bytes())
require.NoError(t, err)
track.Media.Attributes = append(track.Media.Attributes, psdp.Attribute{
Key: "control",
Value: "trackID=0",
})
_, err = c.Setup(true, track, baseURL, 0, 0)
var res base.Response
err = res.Read(br)
require.NoError(t, err)
require.Equal(t, base.StatusOK, res.StatusCode)
}
}()
@ -326,7 +381,7 @@ func TestCorePathRunOnReady(t *testing.T) {
require.Equal(t, true, ok)
defer p.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
c := gortsplib.Client{}
@ -360,7 +415,7 @@ func TestCoreHotReloading(t *testing.T) {
func() {
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
c := gortsplib.Client{}
@ -380,7 +435,7 @@ func TestCoreHotReloading(t *testing.T) {
func() {
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
conn := gortsplib.Client{}

View file

@ -276,37 +276,32 @@ func (m *hlsMuxer) runInner(innerCtx context.Context, innerReady chan struct{})
m.path.onReaderRemove(pathReaderRemoveReq{author: m})
}()
var videoTrack *gortsplib.Track
var videoTrack *gortsplib.TrackH264
videoTrackID := -1
var h264Decoder *rtph264.Decoder
var audioTrack *gortsplib.Track
var audioTrack *gortsplib.TrackAAC
audioTrackID := -1
var aacDecoder *rtpaac.Decoder
for i, t := range res.stream.tracks() {
if t.IsH264() {
for i, track := range res.stream.tracks() {
switch tt := track.(type) {
case *gortsplib.TrackH264:
if videoTrack != nil {
return fmt.Errorf("can't read track %d with HLS: too many tracks", i+1)
return fmt.Errorf("can't encode track %d with HLS: too many tracks", i+1)
}
videoTrack = t
videoTrack = tt
videoTrackID = i
h264Decoder = rtph264.NewDecoder()
} else if t.IsAAC() {
case *gortsplib.TrackAAC:
if audioTrack != nil {
return fmt.Errorf("can't read track %d with HLS: too many tracks", i+1)
return fmt.Errorf("can't encode track %d with HLS: too many tracks", i+1)
}
audioTrack = t
audioTrack = tt
audioTrackID = i
conf, err := t.ExtractConfigAAC()
if err != nil {
return err
}
aacDecoder = rtpaac.NewDecoder(conf.SampleRate)
aacDecoder = rtpaac.NewDecoder(track.ClockRate())
}
}

View file

@ -99,7 +99,7 @@ func (s *hlsSource) runInner() bool {
}
}()
onTracks := func(videoTrack *gortsplib.Track, audioTrack *gortsplib.Track) error {
onTracks := func(videoTrack gortsplib.Track, audioTrack gortsplib.Track) error {
var tracks gortsplib.Tracks
if videoTrack != nil {

View file

@ -30,7 +30,7 @@ func TestMetrics(t *testing.T) {
defer p.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
source := gortsplib.Client{}

View file

@ -249,32 +249,33 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
c.state = gortsplib.ServerSessionStateRead
c.stateMutex.Unlock()
var videoTrack *gortsplib.Track
var videoTrack *gortsplib.TrackH264
videoTrackID := -1
var h264Decoder *rtph264.Decoder
var audioTrack *gortsplib.Track
var audioTrack *gortsplib.TrackAAC
audioTrackID := -1
var audioClockRate int
var aacDecoder *rtpaac.Decoder
for i, t := range res.stream.tracks() {
if t.IsH264() {
for i, track := range res.stream.tracks() {
switch tt := track.(type) {
case *gortsplib.TrackH264:
if videoTrack != nil {
return fmt.Errorf("can't read track %d with RTMP: too many tracks", i+1)
}
videoTrack = t
videoTrack = tt
videoTrackID = i
h264Decoder = rtph264.NewDecoder()
} else if t.IsAAC() {
case *gortsplib.TrackAAC:
if audioTrack != nil {
return fmt.Errorf("can't read track %d with RTMP: too many tracks", i+1)
}
audioTrack = t
audioTrack = tt
audioTrackID = i
audioClockRate, _ = audioTrack.ClockRate()
aacDecoder = rtpaac.NewDecoder(audioClockRate)
aacDecoder = rtpaac.NewDecoder(track.ClockRate())
}
}
@ -283,7 +284,10 @@ func (c *rtmpConn) runRead(ctx context.Context) error {
}
c.conn.SetWriteDeadline(time.Now().Add(time.Duration(c.writeTimeout)))
c.conn.WriteMetadata(videoTrack, audioTrack)
err := c.conn.WriteMetadata(videoTrack, audioTrack)
if err != nil {
return err
}
c.ringBuffer = ringbuffer.New(uint64(c.readBufferCount))
@ -456,8 +460,7 @@ func (c *rtmpConn) runPublish(ctx context.Context) error {
var aacEncoder *rtpaac.Encoder
if audioTrack != nil {
clockRate, _ := audioTrack.ClockRate()
aacEncoder = rtpaac.NewEncoder(96, clockRate, nil, nil, nil)
aacEncoder = rtpaac.NewEncoder(96, audioTrack.ClockRate(), nil, nil, nil)
audioTrackID = len(tracks)
tracks = append(tracks, audioTrack)
}

View file

@ -142,8 +142,7 @@ func (s *rtmpSource) runInner() bool {
var aacEncoder *rtpaac.Encoder
if audioTrack != nil {
clockRate, _ := audioTrack.ClockRate()
aacEncoder = rtpaac.NewEncoder(96, clockRate, nil, nil, nil)
aacEncoder = rtpaac.NewEncoder(96, audioTrack.ClockRate(), nil, nil, nil)
audioTrackID = len(tracks)
tracks = append(tracks, audioTrack)
}

View file

@ -230,7 +230,7 @@ func TestRTSPServerAuth(t *testing.T) {
}
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
source := gortsplib.Client{}
@ -268,7 +268,7 @@ func TestRTSPServerAuth(t *testing.T) {
defer p.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
source := gortsplib.Client{}
@ -314,7 +314,7 @@ func TestRTSPServerAuthFail(t *testing.T) {
defer p.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
c := gortsplib.Client{}
@ -377,7 +377,7 @@ func TestRTSPServerAuthFail(t *testing.T) {
defer p.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
c := gortsplib.Client{}
@ -401,7 +401,7 @@ func TestRTSPServerAuthFail(t *testing.T) {
defer a.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
c := gortsplib.Client{}
@ -434,7 +434,7 @@ func TestRTSPServerPublisherOverride(t *testing.T) {
defer p.close()
track, err := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x01, 0x02, 0x03, 0x04}})
[]byte{0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, nil)
require.NoError(t, err)
s1 := gortsplib.Client{}

View file

@ -41,10 +41,10 @@ type rtspSession struct {
path *path
state gortsplib.ServerSessionState
stateMutex sync.Mutex
setuppedTracks map[int]*gortsplib.Track // read
onReadCmd *externalcmd.Cmd // read
announcedTracks gortsplib.Tracks // publish
stream *stream // publish
setuppedTracks map[int]gortsplib.Track // read
onReadCmd *externalcmd.Cmd // read
announcedTracks gortsplib.Tracks // publish
stream *stream // publish
}
func newRTSPSession(
@ -126,30 +126,11 @@ func (s *rtspSession) onClose(err error) {
// onAnnounce is called by rtspServer.
func (s *rtspSession) onAnnounce(c *rtspConn, ctx *gortsplib.ServerHandlerOnAnnounceCtx) (*base.Response, error) {
for i, track := range ctx.Tracks {
if track.IsH264() {
_, err := track.ExtractConfigH264()
if err != nil {
if th264, ok := track.(*gortsplib.TrackH264); ok {
if th264.SPS() == nil || th264.PPS() == nil {
return &base.Response{
StatusCode: base.StatusBadRequest,
}, fmt.Errorf("H264 track %d is not valid: %v", i+1, err)
}
}
if track.IsAAC() {
_, err := track.ExtractConfigAAC()
if err != nil {
return &base.Response{
StatusCode: base.StatusBadRequest,
}, fmt.Errorf("AAC track %d is not valid: %v", i+1, err)
}
}
if track.IsOpus() {
_, err := track.ExtractConfigOpus()
if err != nil {
return &base.Response{
StatusCode: base.StatusBadRequest,
}, fmt.Errorf("Opus track %d is not valid: %v", i+1, err)
}, fmt.Errorf("track %d can't be used: H264 SPS or PPS not provided into the SDP", i)
}
}
}
@ -257,7 +238,7 @@ func (s *rtspSession) onSetup(c *rtspConn, ctx *gortsplib.ServerHandlerOnSetupCt
}
if s.setuppedTracks == nil {
s.setuppedTracks = make(map[int]*gortsplib.Track)
s.setuppedTracks = make(map[int]gortsplib.Track)
}
s.setuppedTracks[ctx.TrackID] = res.stream.tracks()[ctx.TrackID]

View file

@ -239,20 +239,21 @@ func (s *rtspSource) runInner() bool {
}
func (s *rtspSource) handleMissingH264Params(c *gortsplib.Client, tracks gortsplib.Tracks) error {
h264TrackID := func() int {
h264Track, h264TrackID := func() (*gortsplib.TrackH264, int) {
for i, t := range tracks {
if t.IsH264() {
return i
if th264, ok := t.(*gortsplib.TrackH264); ok {
if th264.SPS() == nil {
return th264, i
}
}
}
return -1
return nil, -1
}()
if h264TrackID < 0 {
return nil
}
_, err := tracks[h264TrackID].ExtractConfigH264()
if err == nil {
if h264Track.SPS() != nil && h264Track.PPS() != nil {
return nil
}
@ -261,7 +262,6 @@ func (s *rtspSource) handleMissingH264Params(c *gortsplib.Client, tracks gortspl
var streamMutex sync.RWMutex
var stream *stream
var payloadType uint8
decoder := rtph264.NewDecoder()
var sps []byte
var pps []byte
@ -293,8 +293,6 @@ func (s *rtspSource) handleMissingH264Params(c *gortsplib.Client, tracks gortspl
return
}
payloadType = pkt.Header.PayloadType
for _, nalu := range nalus {
typ := h264.NALUType(nalu[0] & 0x1F)
switch typ {
@ -325,7 +323,7 @@ func (s *rtspSource) handleMissingH264Params(c *gortsplib.Client, tracks gortspl
}
}
_, err = c.Play(nil)
_, err := c.Play(nil)
if err != nil {
return err
}
@ -348,15 +346,8 @@ func (s *rtspSource) handleMissingH264Params(c *gortsplib.Client, tracks gortspl
case <-paramsReceived:
s.log(logger.Info, "H264 parameters extracted")
track, err := gortsplib.NewTrackH264(payloadType, &gortsplib.TrackConfigH264{
SPS: sps,
PPS: pps,
})
if err != nil {
return err
}
tracks[h264TrackID] = track
h264Track.SetSPS(sps)
h264Track.SetPPS(pps)
res := s.parent.onSourceStaticSetReady(pathSourceStaticSetReadyReq{
source: s,

View file

@ -11,7 +11,6 @@ import (
"github.com/aler9/gortsplib/pkg/base"
"github.com/aler9/gortsplib/pkg/rtph264"
"github.com/pion/rtp"
psdp "github.com/pion/sdp/v3"
"github.com/stretchr/testify/require"
)
@ -41,8 +40,7 @@ func TestRTSPSource(t *testing.T) {
"tls",
} {
t.Run(source, func(t *testing.T) {
track, _ := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x05, 0x06}})
track, _ := gortsplib.NewTrackH264(96, []byte{0x01, 0x02, 0x03, 0x04}, []byte{0x05, 0x06}, nil)
stream := gortsplib.NewServerStream(gortsplib.Tracks{track})
var authValidator *auth.Validator
@ -151,8 +149,7 @@ func TestRTSPSource(t *testing.T) {
}
func TestRTSPSourceNoPassword(t *testing.T) {
track, _ := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x05, 0x06}})
track, _ := gortsplib.NewTrackH264(96, []byte{0x01, 0x02, 0x03, 0x04}, []byte{0x05, 0x06}, nil)
stream := gortsplib.NewServerStream(gortsplib.Tracks{track})
var authValidator *auth.Validator
done := make(chan struct{})
@ -210,15 +207,8 @@ func TestRTSPSourceNoPassword(t *testing.T) {
}
func TestRTSPSourceMissingH264Params(t *testing.T) {
track, _ := gortsplib.NewTrackH264(96,
&gortsplib.TrackConfigH264{SPS: []byte{0x01, 0x02, 0x03, 0x04}, PPS: []byte{0x05, 0x06}})
var newattrs []psdp.Attribute
for _, attr := range track.Media.Attributes {
if attr.Key != "fmtp" {
newattrs = append(newattrs, attr)
}
}
track.Media.Attributes = newattrs
track, err := gortsplib.NewTrackH264(96, nil, nil, nil)
require.NoError(t, err)
stream := gortsplib.NewServerStream(gortsplib.Tracks{track})
@ -275,7 +265,7 @@ func TestRTSPSourceMissingH264Params(t *testing.T) {
},
RTSPAddress: "127.0.0.1:8555",
}
err := s.Start()
err = s.Start()
require.NoError(t, err)
defer s.Wait()
defer s.Close()
@ -314,10 +304,10 @@ func TestRTSPSourceMissingH264Params(t *testing.T) {
require.NoError(t, err)
defer c.Close()
conf, err := c.Tracks()[0].ExtractConfigH264()
require.NoError(t, err)
require.Equal(t, []byte{7, 1, 2, 3}, conf.SPS)
require.Equal(t, []byte{8}, conf.PPS)
h264Track, ok := c.Tracks()[0].(*gortsplib.TrackH264)
require.Equal(t, true, ok)
require.Equal(t, []byte{7, 1, 2, 3}, h264Track.SPS())
require.Equal(t, []byte{8}, h264Track.PPS())
<-received
}