diff --git a/README.md b/README.md index f749969f..238c529a 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Features: * [client-read-options](examples/client-read-options/main.go) * [client-read-pause](examples/client-read-pause/main.go) * [client-read-republish](examples/client-read-republish/main.go) +* [client-read-format-av1](examples/client-read-format-av1/main.go) * [client-read-format-g711](examples/client-read-format-g711/main.go) * [client-read-format-g722](examples/client-read-format-g722/main.go) * [client-read-format-h264](examples/client-read-format-h264/main.go) diff --git a/examples/client-read-format-av1/main.go b/examples/client-read-format-av1/main.go new file mode 100644 index 00000000..bf4dc62f --- /dev/null +++ b/examples/client-read-format-av1/main.go @@ -0,0 +1,88 @@ +package main + +import ( + "log" + + "github.com/bluenviron/gortsplib/v4" + "github.com/bluenviron/gortsplib/v4/pkg/format" + "github.com/bluenviron/gortsplib/v4/pkg/format/rtpvp9" + "github.com/bluenviron/gortsplib/v4/pkg/url" + "github.com/pion/rtp" +) + +// This example shows how to +// 1. connect to a RTSP server +// 2. check if there's a AV1 media +// 3. get access units of that media + +func main() { + c := gortsplib.Client{} + + // parse URL + u, err := url.Parse("rtsp://localhost:8554/mystream") + if err != nil { + panic(err) + } + + // connect to the server + err = c.Start(u.Scheme, u.Host) + if err != nil { + panic(err) + } + defer c.Close() + + // find published medias + desc, _, err := c.Describe(u) + if err != nil { + panic(err) + } + + // find the AV1 media and format + var forma *format.AV1 + medi := desc.FindFormat(&forma) + if medi == nil { + panic("media not found") + } + + // create decoder + rtpDec, err := forma.CreateDecoder() + if err != nil { + panic(err) + } + + // setup a single media + _, err = c.Setup(desc.BaseURL, medi, 0, 0) + if err != nil { + panic(err) + } + + // called when a RTP packet arrives + c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) { + // decode timestamp + pts, ok := c.PacketPTS(medi, pkt) + if !ok { + log.Printf("waiting for timestamp") + return + } + + // extract AV1 temporal units from RTP packets + tu, err := rtpDec.Decode(pkt) + if err != nil { + if err != rtpvp9.ErrNonStartingPacketAndNoPrevious && err != rtpvp9.ErrMorePacketsNeeded { + log.Printf("ERR: %v", err) + } + return + } + + log.Printf("received temporal unit with PTS %v and size %d\n", pts, len(tu)) + }) + + // start playing + _, err = c.Play(nil) + if err != nil { + panic(err) + } + + // wait until a fatal error + panic(c.Wait()) +} diff --git a/examples/client-read-format-g711/main.go b/examples/client-read-format-g711/main.go index fd370054..f643617f 100644 --- a/examples/client-read-format-g711/main.go +++ b/examples/client-read-format-g711/main.go @@ -60,6 +60,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return } diff --git a/examples/client-read-format-g722/main.go b/examples/client-read-format-g722/main.go index 287792ac..ae14e6b9 100644 --- a/examples/client-read-format-g722/main.go +++ b/examples/client-read-format-g722/main.go @@ -60,6 +60,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return } diff --git a/examples/client-read-format-lpcm/main.go b/examples/client-read-format-lpcm/main.go index 0c660a81..4db53936 100644 --- a/examples/client-read-format-lpcm/main.go +++ b/examples/client-read-format-lpcm/main.go @@ -60,6 +60,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return } diff --git a/examples/client-read-format-mjpeg/main.go b/examples/client-read-format-mjpeg/main.go index 27aee492..7a0b3e0b 100644 --- a/examples/client-read-format-mjpeg/main.go +++ b/examples/client-read-format-mjpeg/main.go @@ -64,6 +64,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return } diff --git a/examples/client-read-format-mpeg4audio-save-to-disk/main.go b/examples/client-read-format-mpeg4audio-save-to-disk/main.go index 78dbf7e1..15fd17a8 100644 --- a/examples/client-read-format-mpeg4audio-save-to-disk/main.go +++ b/examples/client-read-format-mpeg4audio-save-to-disk/main.go @@ -66,6 +66,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return } diff --git a/examples/client-read-format-mpeg4audio/main.go b/examples/client-read-format-mpeg4audio/main.go index b12b785b..1b539a03 100644 --- a/examples/client-read-format-mpeg4audio/main.go +++ b/examples/client-read-format-mpeg4audio/main.go @@ -60,6 +60,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return } diff --git a/examples/client-read-format-opus/main.go b/examples/client-read-format-opus/main.go index d613774f..7a027bf3 100644 --- a/examples/client-read-format-opus/main.go +++ b/examples/client-read-format-opus/main.go @@ -60,6 +60,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return } diff --git a/examples/client-read-format-vp8/main.go b/examples/client-read-format-vp8/main.go index 6dbe6c36..45a260a3 100644 --- a/examples/client-read-format-vp8/main.go +++ b/examples/client-read-format-vp8/main.go @@ -61,6 +61,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return } diff --git a/examples/client-read-format-vp9/main.go b/examples/client-read-format-vp9/main.go index 8c9ebd71..529fcf68 100644 --- a/examples/client-read-format-vp9/main.go +++ b/examples/client-read-format-vp9/main.go @@ -61,6 +61,7 @@ func main() { // decode timestamp pts, ok := c.PacketPTS(medi, pkt) if !ok { + log.Printf("waiting for timestamp") return }