mirror of
https://github.com/aler9/gortsplib
synced 2025-09-27 03:25:52 +08:00
improve examples (#778)
This commit is contained in:
@@ -95,8 +95,8 @@ Features:
|
||||
* [server](examples/server/main.go)
|
||||
* [server-tls](examples/server-tls/main.go)
|
||||
* [server-auth](examples/server-auth/main.go)
|
||||
* [server-h264-to-disk](examples/server-h264-to-disk/main.go)
|
||||
* [server-h264-from-disk](examples/server-h264-from-disk/main.go)
|
||||
* [server-record-format-h264-to-disk](examples/server-record-format-h264-to-disk/main.go)
|
||||
* [server-play-format-h264-from-disk](examples/server-play-format-h264-from-disk/main.go)
|
||||
* [proxy](examples/proxy/main.go)
|
||||
|
||||
## API Documentation
|
||||
|
@@ -13,9 +13,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. generate a dummy G711 audio stream
|
||||
// 2. connect to a RTSP server, find a back channel that supports G711
|
||||
// 3. route the G711 stream to the channel
|
||||
// 1. generate a dummy G711 audio stream.
|
||||
// 2. connect to a RTSP server, find a back channel that supports G711.
|
||||
// 3. route the G711 stream to the channel.
|
||||
|
||||
func multiplyAndDivide(v, m, d int64) int64 {
|
||||
secs := v / d
|
||||
@@ -72,7 +72,7 @@ func main() {
|
||||
// find the back channel
|
||||
medi, forma := findG711BackChannel(desc)
|
||||
if medi == nil {
|
||||
panic("media not found")
|
||||
panic("back channel not found")
|
||||
}
|
||||
|
||||
// setup a single media
|
||||
@@ -137,7 +137,7 @@ func main() {
|
||||
for _, pkt := range pkts {
|
||||
pkt.Timestamp += uint32(int64(randomStart) + prevPTS)
|
||||
|
||||
err = c.WritePacketRTP(desc.Medias[0], pkt)
|
||||
err = c.WritePacketRTP(medi, pkt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@@ -19,10 +19,10 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a AV1 stream
|
||||
// 3. decode the AV1 stream into RGBA frames
|
||||
// 4. convert RGBA frames to JPEG images and save them on disk
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a AV1 stream.
|
||||
// 3. decode the AV1 stream into RGBA frames.
|
||||
// 4. convert RGBA frames to JPEG images and save them on disk.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -14,9 +14,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a AV1 stream
|
||||
// 3. decode the AV1 stream into RGBA frames
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a AV1 stream.
|
||||
// 3. decode the AV1 stream into RGBA frames.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a G711 stream
|
||||
// 3. decode the G711 stream into audio samples
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a G711 stream.
|
||||
// 3. decode the G711 stream into audio samples.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a H264 stream and a MPEG-4 audio stream
|
||||
// 3. save the content of those formats in a file in MPEG-TS format
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a H264 stream and a MPEG-4 audio stream.
|
||||
// 3. save the content of those formats in a file in MPEG-TS format.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -50,7 +50,11 @@ func (e *mpegtsMuxer) initialize() error {
|
||||
},
|
||||
}
|
||||
|
||||
e.w = mpegts.NewWriter(e.b, []*mpegts.Track{e.h264Track, e.mpeg4AudioTrack})
|
||||
e.w = &mpegts.Writer{W: e.b, Tracks: []*mpegts.Track{e.h264Track, e.mpeg4AudioTrack}}
|
||||
err = e.w.Initialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a H264 stream
|
||||
// 3. save the content of the format in a file in MPEG-TS format
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a H264 stream.
|
||||
// 3. save the content of the format in a file in MPEG-TS format.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -34,7 +34,11 @@ func (e *mpegtsMuxer) initialize() error {
|
||||
Codec: &mpegts.CodecH264{},
|
||||
}
|
||||
|
||||
e.w = mpegts.NewWriter(e.b, []*mpegts.Track{e.track})
|
||||
e.w = &mpegts.Writer{W: e.b, Tracks: []*mpegts.Track{e.track}}
|
||||
err = e.w.Initialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -19,10 +19,10 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a H264 stream
|
||||
// 3. decode the H264 stream into RGBA frames
|
||||
// 4. convert RGBA frames to JPEG images and save them on disk
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a H264 stream.
|
||||
// 3. decode the H264 stream into RGBA frames.
|
||||
// 4. convert RGBA frames to JPEG images and save them on disk.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -14,9 +14,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's an H264 stream
|
||||
// 3. decode the H264 stream into RGBA frames
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's an H264 stream.
|
||||
// 3. decode the H264 stream into RGBA frames.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a H265 stream
|
||||
// 3. save the content of the format in a file in MPEG-TS format
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a H265 stream.
|
||||
// 3. save the content of the format in a file in MPEG-TS format.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -35,7 +35,11 @@ func (e *mpegtsMuxer) initialize() error {
|
||||
Codec: &mpegts.CodecH265{},
|
||||
}
|
||||
|
||||
e.w = mpegts.NewWriter(e.b, []*mpegts.Track{e.track})
|
||||
e.w = &mpegts.Writer{W: e.b, Tracks: []*mpegts.Track{e.track}}
|
||||
err = e.w.Initialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -19,10 +19,10 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a H265 stream
|
||||
// 3. decode the H265 stream into RGBA frames
|
||||
// 4. convert RGBA frames to JPEG images and save them on disk
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a H265 stream.
|
||||
// 3. decode the H265 stream into RGBA frames.
|
||||
// 4. convert RGBA frames to JPEG images and save them on disk.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -14,9 +14,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a H265 stream
|
||||
// 3. decode the H265 stream into RGBA frames
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a H265 stream.
|
||||
// 3. decode the H265 stream into RGBA frames.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -10,9 +10,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a LPCM stream
|
||||
// 3. get LPCM samples of that format
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a LPCM stream.
|
||||
// 3. get LPCM samples of that format.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -13,10 +13,10 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a M-JPEG stream
|
||||
// 3. get JPEG images of that format
|
||||
// 4. decode JPEG images into RGBA frames
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a M-JPEG stream.
|
||||
// 3. get JPEG images of that format.
|
||||
// 4. decode JPEG images into RGBA frames.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a MPEG-4 audio stream
|
||||
// 3. save the content of the format in a file in MPEG-TS format
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a MPEG-4 audio stream.
|
||||
// 3. save the content of the format in a file in MPEG-TS format.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -34,7 +34,11 @@ func (e *mpegtsMuxer) initialize() error {
|
||||
}
|
||||
e.b = bufio.NewWriter(e.f)
|
||||
|
||||
e.w = mpegts.NewWriter(e.b, []*mpegts.Track{e.track})
|
||||
e.w = &mpegts.Writer{W: e.b, Tracks: []*mpegts.Track{e.track}}
|
||||
err = e.w.Initialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -10,9 +10,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a MPEG-4 audio stream
|
||||
// 3. get access units of that format
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a MPEG-4 audio stream.
|
||||
// 3. get access units of that format.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a Opus stream
|
||||
// 3. save the content of the format in a file in MPEG-TS format
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a Opus stream.
|
||||
// 3. save the content of the format in a file in MPEG-TS format.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -34,7 +34,11 @@ func (e *mpegtsMuxer) initialize() error {
|
||||
}
|
||||
e.b = bufio.NewWriter(e.f)
|
||||
|
||||
e.w = mpegts.NewWriter(e.b, []*mpegts.Track{e.track})
|
||||
e.w = &mpegts.Writer{W: e.b, Tracks: []*mpegts.Track{e.track}}
|
||||
err = e.w.Initialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -10,9 +10,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's an Opus stream
|
||||
// 3. get Opus packets of that format
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's an Opus stream.
|
||||
// 3. get Opus packets of that format.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -13,9 +13,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a VP8 stream
|
||||
// 3. decode the VP8 stream into RGBA frames
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a VP8 stream.
|
||||
// 3. decode the VP8 stream into RGBA frames.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -13,9 +13,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. check if there's a VP9 stream
|
||||
// 3. decode the VP9 stream into RGBA frames
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. check if there's a VP9 stream.
|
||||
// 3. decode the VP9 stream into RGBA frames.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -13,8 +13,8 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. set additional client options
|
||||
// 2. connect to a RTSP server and read all medias on a path
|
||||
// 1. set additional client options.
|
||||
// 2. connect to a RTSP server and read all medias on a path.
|
||||
|
||||
func main() {
|
||||
// Client allows to set additional client options
|
||||
|
@@ -13,10 +13,10 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server and read all medias on a path
|
||||
// 2. wait for 5 seconds
|
||||
// 3. pause for 5 seconds
|
||||
// 4. repeat
|
||||
// 1. connect to a RTSP server and read all medias on a path.
|
||||
// 2. wait for 5 seconds.
|
||||
// 3. pause for 5 seconds.
|
||||
// 4. repeat.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -11,9 +11,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. read all media streams on a path
|
||||
// 3. Get the PTS and NTP timestamp of incoming RTP packets
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. read all media streams on a path.
|
||||
// 3. Get the PTS and NTP timestamp of incoming RTP packets.
|
||||
|
||||
func main() {
|
||||
c := gortsplib.Client{}
|
||||
|
@@ -11,8 +11,8 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 2. read all medias on a path
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. read all medias on a path.
|
||||
// 3. re-publish all medias on another path.
|
||||
|
||||
func main() {
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. read all media streams on a path.
|
||||
|
||||
func main() {
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server
|
||||
// 1. connect to a RTSP server.
|
||||
// 2. get and print informations about medias published on a path.
|
||||
|
||||
func main() {
|
||||
|
@@ -13,11 +13,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce an AV1 format
|
||||
// 2. generate dummy RGBA images
|
||||
// 3. encode images with AV1
|
||||
// 4. generate RTP packets from AV1
|
||||
// 5. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce an AV1 format.
|
||||
// 2. generate dummy RGBA images.
|
||||
// 3. encode images with AV1.
|
||||
// 4. generate RTP packets from AV1.
|
||||
// 5. write RTP packets to the server.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -12,11 +12,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce a G711 format
|
||||
// 2. generate dummy LPCM audio samples
|
||||
// 3. encode audio samples with G711
|
||||
// 3. generate RTP packets from G711 samples
|
||||
// 4. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce a G711 format.
|
||||
// 2. generate dummy LPCM audio samples.
|
||||
// 3. encode audio samples with G711.
|
||||
// 3. generate RTP packets from G711 samples.
|
||||
// 4. write RTP packets to the server.
|
||||
|
||||
func multiplyAndDivide(v, m, d int64) int64 {
|
||||
secs := v / d
|
||||
|
@@ -17,10 +17,10 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. read H264 frames from a video file in MPEG-TS format
|
||||
// 2. connect to a RTSP server, announce a H264 format
|
||||
// 3. wrap frames into RTP packets
|
||||
// 4. write RTP packets to the server
|
||||
// 1. read H264 frames from a video file in MPEG-TS format.
|
||||
// 2. connect to a RTSP server, announce a H264 format.
|
||||
// 3. wrap frames into RTP packets.
|
||||
// 4. write RTP packets to the server.
|
||||
|
||||
func findTrack(r *mpegts.Reader) (*mpegts.Track, error) {
|
||||
for _, track := range r.Tracks() {
|
||||
|
@@ -13,11 +13,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce an H264 format
|
||||
// 2. generate dummy RGBA images
|
||||
// 3. encode images with H264
|
||||
// 4. generate RTP packets from H264
|
||||
// 5. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce an H264 format.
|
||||
// 2. generate dummy RGBA images.
|
||||
// 3. encode images with H264.
|
||||
// 4. generate RTP packets from H264.
|
||||
// 5. write RTP packets to the server.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -13,11 +13,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce an H265 format
|
||||
// 2. generate dummy RGBA images
|
||||
// 3. encode images with H265
|
||||
// 4. generate RTP packets from H265
|
||||
// 5. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce an H265 format.
|
||||
// 2. generate dummy RGBA images.
|
||||
// 3. encode images with H265.
|
||||
// 4. generate RTP packets from H265.
|
||||
// 5. write RTP packets to the server.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -11,10 +11,10 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce an LPCM format
|
||||
// 2. generate dummy LPCM audio samples
|
||||
// 3. generate RTP packets from LPCM audio samples
|
||||
// 4. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce an LPCM format.
|
||||
// 2. generate dummy LPCM audio samples.
|
||||
// 3. generate RTP packets from LPCM audio samples.
|
||||
// 4. write RTP packets to the server.
|
||||
|
||||
func multiplyAndDivide(v, m, d int64) int64 {
|
||||
secs := v / d
|
||||
|
@@ -13,11 +13,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce a M-JPEG format
|
||||
// 2. generate dummy RGBA images
|
||||
// 3. encode images with JPEG
|
||||
// 4. generate RTP packets from JPEG
|
||||
// 5. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce a M-JPEG format.
|
||||
// 2. generate dummy RGBA images.
|
||||
// 3. encode images with JPEG.
|
||||
// 4. generate RTP packets from JPEG.
|
||||
// 5. write RTP packets to the server.
|
||||
|
||||
func multiplyAndDivide(v, m, d int64) int64 {
|
||||
secs := v / d
|
||||
|
@@ -14,11 +14,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce a MPEG-4 Audio (AAC) format
|
||||
// 2. generate dummy LPCM audio samples
|
||||
// 3. encode audio samples with MPEG-4 Audio (AAC)
|
||||
// 3. generate RTP packets from MPEG-4 Audio units
|
||||
// 4. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce a MPEG-4 Audio (AAC) format.
|
||||
// 2. generate dummy LPCM audio samples.
|
||||
// 3. encode audio samples with MPEG-4 Audio (AAC).
|
||||
// 3. generate RTP packets from MPEG-4 Audio units.
|
||||
// 4. write RTP packets to the server.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev gcc pkg-config
|
||||
|
@@ -16,11 +16,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce a Opus format
|
||||
// 2. generate dummy LPCM audio samples
|
||||
// 3. encode audio samples with Opus
|
||||
// 3. generate RTP packets from Opus packets
|
||||
// 4. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce a Opus format.
|
||||
// 2. generate dummy LPCM audio samples.
|
||||
// 3. encode audio samples with Opus.
|
||||
// 3. generate RTP packets from Opus packets.
|
||||
// 4. write RTP packets to the server.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev gcc pkg-config
|
||||
|
@@ -13,11 +13,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce a VP8 format
|
||||
// 2. generate dummy RGBA images
|
||||
// 3. encode images with VP8
|
||||
// 4. generate RTP packets from VP8
|
||||
// 5. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce a VP8 format.
|
||||
// 2. generate dummy RGBA images.
|
||||
// 3. encode images with VP8.
|
||||
// 4. generate RTP packets from VP8.
|
||||
// 5. write RTP packets to the server.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -13,11 +13,11 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce a VP9 format
|
||||
// 2. generate dummy RGBA images
|
||||
// 3. encode images with VP9
|
||||
// 4. generate RTP packets from VP9
|
||||
// 5. write RTP packets to the server
|
||||
// 1. connect to a RTSP server, announce a VP9 format.
|
||||
// 2. generate dummy RGBA images.
|
||||
// 3. encode images with VP9.
|
||||
// 4. generate RTP packets from VP9.
|
||||
// 5. write RTP packets to the server.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -13,12 +13,12 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. set additional client options
|
||||
// 2. connect to a RTSP server, announce an H264 format
|
||||
// 3. generate dummy RGBA images
|
||||
// 4. encode images with H264
|
||||
// 5. generate RTP packets from H264
|
||||
// 6. write RTP packets to the server
|
||||
// 1. set additional client options.
|
||||
// 2. connect to a RTSP server, announce an H264 format.
|
||||
// 3. generate dummy RGBA images.
|
||||
// 4. encode images with H264.
|
||||
// 5. generate RTP packets from H264.
|
||||
// 6. write RTP packets to the server.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -13,13 +13,13 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. connect to a RTSP server, announce an H264 format
|
||||
// 2. generate dummy RGBA images
|
||||
// 3. encode images with H264
|
||||
// 4. generate RTP packets from H264
|
||||
// 5. write RTP packets to the server for 5 seconds
|
||||
// 6. pause for 5 seconds
|
||||
// 7. repeat
|
||||
// 1. connect to a RTSP server, announce an H264 format.
|
||||
// 2. generate dummy RGBA images.
|
||||
// 3. encode images with H264.
|
||||
// 4. generate RTP packets from H264.
|
||||
// 5. write RTP packets to the server for 5 seconds.
|
||||
// 6. pause for 5 seconds.
|
||||
// 7. repeat.
|
||||
|
||||
// This example requires the FFmpeg libraries, that can be installed with this command:
|
||||
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
|
||||
|
@@ -62,6 +62,7 @@ func (c *client) read() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// notify the server that we are ready
|
||||
stream := c.server.setStreamReady(desc)
|
||||
defer c.server.setStreamUnready()
|
||||
|
||||
|
@@ -4,8 +4,8 @@ import "log"
|
||||
|
||||
// This example shows how to
|
||||
// 1. create a server that serves a single stream.
|
||||
// 2. create a client, read an existing stream from an external server or camera,
|
||||
// pass the stream to the server in order to serve it.
|
||||
// 2. create a client, that reads an existing stream from another server or camera.
|
||||
// 3. route the stream from the client to the server, and from the server to all connected readers.
|
||||
|
||||
func main() {
|
||||
// allocate the server.
|
||||
@@ -13,11 +13,11 @@ func main() {
|
||||
s.initialize()
|
||||
|
||||
// allocate the client.
|
||||
// give client access to the server.
|
||||
// allow client to use the server.
|
||||
c := &client{server: s}
|
||||
c.initialize()
|
||||
|
||||
// start server and wait until a fatal error
|
||||
log.Printf("server is ready on %s", s.server.RTSPAddress)
|
||||
s.server.StartAndWait()
|
||||
panic(s.server.StartAndWait())
|
||||
}
|
||||
|
@@ -19,9 +19,9 @@ func (s *server) initialize() {
|
||||
// configure the server
|
||||
s.server = &gortsplib.Server{
|
||||
Handler: s,
|
||||
RTSPAddress: ":8554",
|
||||
UDPRTPAddress: ":8000",
|
||||
UDPRTCPAddress: ":8001",
|
||||
RTSPAddress: ":8556",
|
||||
UDPRTPAddress: ":8002",
|
||||
UDPRTCPAddress: ":8003",
|
||||
MulticastIPRange: "224.1.0.0/16",
|
||||
MulticastRTPPort: 8002,
|
||||
MulticastRTCPPort: 8003,
|
||||
@@ -98,20 +98,24 @@ func (s *server) OnPlay(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Response,
|
||||
func (s *server) setStreamReady(desc *description.Session) *gortsplib.ServerStream {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
s.stream = &gortsplib.ServerStream{
|
||||
Server: s.server,
|
||||
Desc: desc,
|
||||
}
|
||||
|
||||
err := s.stream.Initialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return s.stream
|
||||
}
|
||||
|
||||
func (s *server) setStreamUnready() {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
s.stream.Close()
|
||||
s.stream = nil
|
||||
}
|
||||
|
@@ -14,9 +14,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. create a RTSP server which accepts plain connections
|
||||
// 2. allow a single client to publish a stream with TCP or UDP, if it provides credentials
|
||||
// 3. allow multiple clients to read that stream with TCP, UDP or UDP-multicast, if they provide credentials
|
||||
// 1. create a RTSP server which accepts plain connections.
|
||||
// 2. allow a single client to publish a stream with TCP or UDP, if it provides credentials.
|
||||
// 3. allow multiple clients to read the stream with TCP, UDP or UDP-multicast, if they provide credentials.
|
||||
|
||||
const (
|
||||
// credentials required to publish the stream
|
||||
|
@@ -1,266 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/asticode/go-astits"
|
||||
"github.com/bluenviron/gortsplib/v4"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/base"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/formats/mpegts"
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. create a RTSP server which accepts plain connections
|
||||
// 2. read from disk a MPEG-TS file which contains a H264 track
|
||||
// 3. serve the content of the file to connected readers
|
||||
|
||||
func findTrack(r *mpegts.Reader) (*mpegts.Track, error) {
|
||||
for _, track := range r.Tracks() {
|
||||
if _, ok := track.Codec.(*mpegts.CodecH264); ok {
|
||||
return track, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("H264 track not found")
|
||||
}
|
||||
|
||||
func randUint32() (uint32, error) {
|
||||
var b [4]byte
|
||||
_, err := rand.Read(b[:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]), nil
|
||||
}
|
||||
|
||||
func routeFrames(f *os.File, stream *gortsplib.ServerStream) {
|
||||
// setup H264 -> RTP encoder
|
||||
rtpEnc, err := stream.Desc.Medias[0].Formats[0].(*format.H264).CreateEncoder()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
randomStart, err := randUint32()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for {
|
||||
// setup MPEG-TS parser
|
||||
r := &mpegts.Reader{R: f}
|
||||
err = r.Initialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// find the H264 track inside the file
|
||||
track, err := findTrack(r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
timeDecoder := mpegts.TimeDecoder{}
|
||||
timeDecoder.Initialize()
|
||||
|
||||
var firstDTS *int64
|
||||
var firstTime time.Time
|
||||
var lastRTPTime uint32
|
||||
|
||||
// setup a callback that is called when a H264 access unit is read from the file
|
||||
r.OnDataH264(track, func(pts, dts int64, au [][]byte) error {
|
||||
dts = timeDecoder.Decode(dts)
|
||||
pts = timeDecoder.Decode(pts)
|
||||
|
||||
// sleep between access units
|
||||
if firstDTS != nil {
|
||||
timeDrift := time.Duration(dts-*firstDTS)*time.Second/90000 - time.Since(firstTime)
|
||||
if timeDrift > 0 {
|
||||
time.Sleep(timeDrift)
|
||||
}
|
||||
} else {
|
||||
firstTime = time.Now()
|
||||
firstDTS = &dts
|
||||
}
|
||||
|
||||
log.Printf("writing access unit with pts=%d dts=%d", pts, dts)
|
||||
|
||||
// wrap the access unit into RTP packets
|
||||
packets, err := rtpEnc.Encode(au)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// set packet timestamp
|
||||
// we don't have to perform any conversion
|
||||
// since H264 clock rate is the same in both MPEG-TS and RTSP
|
||||
lastRTPTime = uint32(int64(randomStart) + pts)
|
||||
for _, packet := range packets {
|
||||
packet.Timestamp = lastRTPTime
|
||||
}
|
||||
|
||||
// write RTP packets to the server
|
||||
for _, packet := range packets {
|
||||
err := stream.WritePacketRTP(stream.Desc.Medias[0], packet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
// read the file
|
||||
for {
|
||||
err := r.Read()
|
||||
if err != nil {
|
||||
// file has ended
|
||||
if errors.Is(err, astits.ErrNoMorePackets) {
|
||||
log.Printf("file has ended, rewinding")
|
||||
|
||||
// rewind to start position
|
||||
_, err = f.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// keep current timestamp
|
||||
randomStart = lastRTPTime + 1
|
||||
|
||||
break
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type serverHandler struct {
|
||||
server *gortsplib.Server
|
||||
stream *gortsplib.ServerStream
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
// called when a connection is opened.
|
||||
func (sh *serverHandler) OnConnOpen(ctx *gortsplib.ServerHandlerOnConnOpenCtx) {
|
||||
log.Printf("conn opened")
|
||||
}
|
||||
|
||||
// called when a connection is closed.
|
||||
func (sh *serverHandler) OnConnClose(ctx *gortsplib.ServerHandlerOnConnCloseCtx) {
|
||||
log.Printf("conn closed (%v)", ctx.Error)
|
||||
}
|
||||
|
||||
// called when a session is opened.
|
||||
func (sh *serverHandler) OnSessionOpen(ctx *gortsplib.ServerHandlerOnSessionOpenCtx) {
|
||||
log.Printf("session opened")
|
||||
}
|
||||
|
||||
// called when a session is closed.
|
||||
func (sh *serverHandler) OnSessionClose(ctx *gortsplib.ServerHandlerOnSessionCloseCtx) {
|
||||
log.Printf("session closed")
|
||||
}
|
||||
|
||||
// called when receiving a DESCRIBE request.
|
||||
func (sh *serverHandler) OnDescribe(ctx *gortsplib.ServerHandlerOnDescribeCtx) (*base.Response, *gortsplib.ServerStream, error) {
|
||||
log.Printf("DESCRIBE request")
|
||||
|
||||
sh.mutex.RLock()
|
||||
defer sh.mutex.RUnlock()
|
||||
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, sh.stream, nil
|
||||
}
|
||||
|
||||
// called when receiving a SETUP request.
|
||||
func (sh *serverHandler) OnSetup(ctx *gortsplib.ServerHandlerOnSetupCtx) (*base.Response, *gortsplib.ServerStream, error) {
|
||||
log.Printf("SETUP request")
|
||||
|
||||
sh.mutex.RLock()
|
||||
defer sh.mutex.RUnlock()
|
||||
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, sh.stream, nil
|
||||
}
|
||||
|
||||
// called when receiving a PLAY request.
|
||||
func (sh *serverHandler) OnPlay(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Response, error) {
|
||||
log.Printf("PLAY request")
|
||||
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
h := &serverHandler{}
|
||||
|
||||
// prevent clients from connecting to the server until the stream is properly set up
|
||||
h.mutex.Lock()
|
||||
|
||||
// create the server
|
||||
h.server = &gortsplib.Server{
|
||||
Handler: h,
|
||||
RTSPAddress: ":8554",
|
||||
UDPRTPAddress: ":8000",
|
||||
UDPRTCPAddress: ":8001",
|
||||
MulticastIPRange: "224.1.0.0/16",
|
||||
MulticastRTPPort: 8002,
|
||||
MulticastRTCPPort: 8003,
|
||||
}
|
||||
|
||||
// start the server
|
||||
err := h.server.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer h.server.Close()
|
||||
|
||||
// create a RTSP description that contains a H264 format
|
||||
desc := &description.Session{
|
||||
Medias: []*description.Media{{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []format.Format{&format.H264{
|
||||
PayloadTyp: 96,
|
||||
PacketizationMode: 1,
|
||||
}},
|
||||
}},
|
||||
}
|
||||
|
||||
// create a server stream
|
||||
h.stream = &gortsplib.ServerStream{
|
||||
Server: h.server,
|
||||
Desc: desc,
|
||||
}
|
||||
err = h.stream.Initialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer h.stream.Close()
|
||||
|
||||
// open a file in MPEG-TS format
|
||||
f, err := os.Open("myvideo.ts")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// in a separate routine, route frames from file to ServerStream
|
||||
go routeFrames(f, h.stream)
|
||||
|
||||
// allow clients to connect
|
||||
h.mutex.Unlock()
|
||||
|
||||
// wait until a fatal error
|
||||
log.Printf("server is ready on %s", h.server.RTSPAddress)
|
||||
panic(h.server.Wait())
|
||||
}
|
159
examples/server-play-format-h264-from-disk/file_streamer.go
Normal file
159
examples/server-play-format-h264-from-disk/file_streamer.go
Normal file
@@ -0,0 +1,159 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/asticode/go-astits"
|
||||
"github.com/bluenviron/gortsplib/v4"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
"github.com/bluenviron/mediacommon/v2/pkg/formats/mpegts"
|
||||
)
|
||||
|
||||
func randUint32() (uint32, error) {
|
||||
var b [4]byte
|
||||
_, err := rand.Read(b[:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]), nil
|
||||
}
|
||||
|
||||
func findTrack(r *mpegts.Reader) (*mpegts.Track, error) {
|
||||
for _, track := range r.Tracks() {
|
||||
if _, ok := track.Codec.(*mpegts.CodecH264); ok {
|
||||
return track, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("H264 track not found")
|
||||
}
|
||||
|
||||
type fileStreamer struct {
|
||||
stream *gortsplib.ServerStream
|
||||
|
||||
f *os.File
|
||||
}
|
||||
|
||||
func (r *fileStreamer) initialize() error {
|
||||
// open a file in MPEG-TS format
|
||||
var err error
|
||||
r.f, err = os.Open("myvideo.ts")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// in a separate routine, route frames from file to ServerStream
|
||||
go r.run()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *fileStreamer) close() {
|
||||
r.f.Close()
|
||||
}
|
||||
|
||||
func (r *fileStreamer) run() {
|
||||
// setup H264 -> RTP encoder
|
||||
rtpEnc, err := r.stream.Desc.Medias[0].Formats[0].(*format.H264).CreateEncoder()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
randomStart, err := randUint32()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for {
|
||||
// setup MPEG-TS parser
|
||||
mr := &mpegts.Reader{R: r.f}
|
||||
err = mr.Initialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// find the H264 track inside the file
|
||||
track, err := findTrack(mr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
timeDecoder := mpegts.TimeDecoder{}
|
||||
timeDecoder.Initialize()
|
||||
|
||||
var firstDTS *int64
|
||||
var firstTime time.Time
|
||||
var lastRTPTime uint32
|
||||
|
||||
// setup a callback that is called when a H264 access unit is read from the file
|
||||
mr.OnDataH264(track, func(pts, dts int64, au [][]byte) error {
|
||||
dts = timeDecoder.Decode(dts)
|
||||
pts = timeDecoder.Decode(pts)
|
||||
|
||||
// sleep between access units
|
||||
if firstDTS != nil {
|
||||
timeDrift := time.Duration(dts-*firstDTS)*time.Second/90000 - time.Since(firstTime)
|
||||
if timeDrift > 0 {
|
||||
time.Sleep(timeDrift)
|
||||
}
|
||||
} else {
|
||||
firstTime = time.Now()
|
||||
firstDTS = &dts
|
||||
}
|
||||
|
||||
log.Printf("writing access unit with pts=%d dts=%d", pts, dts)
|
||||
|
||||
// wrap the access unit into RTP packets
|
||||
packets, err := rtpEnc.Encode(au)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// set packet timestamp
|
||||
// we don't have to perform any conversion
|
||||
// since H264 clock rate is the same in both MPEG-TS and RTSP
|
||||
lastRTPTime = uint32(int64(randomStart) + pts)
|
||||
for _, packet := range packets {
|
||||
packet.Timestamp = lastRTPTime
|
||||
}
|
||||
|
||||
// write RTP packets to the server
|
||||
for _, packet := range packets {
|
||||
err := r.stream.WritePacketRTP(r.stream.Desc.Medias[0], packet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
// read the file
|
||||
for {
|
||||
err := mr.Read()
|
||||
if err != nil {
|
||||
// file has ended
|
||||
if errors.Is(err, astits.ErrNoMorePackets) {
|
||||
log.Printf("file has ended, rewinding")
|
||||
|
||||
// rewind to start position
|
||||
_, err = r.f.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// keep current timestamp
|
||||
randomStart = lastRTPTime + 1
|
||||
|
||||
break
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
137
examples/server-play-format-h264-from-disk/main.go
Normal file
137
examples/server-play-format-h264-from-disk/main.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/bluenviron/gortsplib/v4"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/base"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format"
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. create a RTSP server which accepts plain connections.
|
||||
// 2. read from disk a MPEG-TS file which contains a H264 track.
|
||||
// 3. serve the content of the file to all connected readers.
|
||||
|
||||
type serverHandler struct {
|
||||
server *gortsplib.Server
|
||||
stream *gortsplib.ServerStream
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
// called when a connection is opened.
|
||||
func (sh *serverHandler) OnConnOpen(ctx *gortsplib.ServerHandlerOnConnOpenCtx) {
|
||||
log.Printf("conn opened")
|
||||
}
|
||||
|
||||
// called when a connection is closed.
|
||||
func (sh *serverHandler) OnConnClose(ctx *gortsplib.ServerHandlerOnConnCloseCtx) {
|
||||
log.Printf("conn closed (%v)", ctx.Error)
|
||||
}
|
||||
|
||||
// called when a session is opened.
|
||||
func (sh *serverHandler) OnSessionOpen(ctx *gortsplib.ServerHandlerOnSessionOpenCtx) {
|
||||
log.Printf("session opened")
|
||||
}
|
||||
|
||||
// called when a session is closed.
|
||||
func (sh *serverHandler) OnSessionClose(ctx *gortsplib.ServerHandlerOnSessionCloseCtx) {
|
||||
log.Printf("session closed")
|
||||
}
|
||||
|
||||
// called when receiving a DESCRIBE request.
|
||||
func (sh *serverHandler) OnDescribe(ctx *gortsplib.ServerHandlerOnDescribeCtx) (*base.Response, *gortsplib.ServerStream, error) {
|
||||
log.Printf("DESCRIBE request")
|
||||
|
||||
sh.mutex.RLock()
|
||||
defer sh.mutex.RUnlock()
|
||||
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, sh.stream, nil
|
||||
}
|
||||
|
||||
// called when receiving a SETUP request.
|
||||
func (sh *serverHandler) OnSetup(ctx *gortsplib.ServerHandlerOnSetupCtx) (*base.Response, *gortsplib.ServerStream, error) {
|
||||
log.Printf("SETUP request")
|
||||
|
||||
sh.mutex.RLock()
|
||||
defer sh.mutex.RUnlock()
|
||||
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, sh.stream, nil
|
||||
}
|
||||
|
||||
// called when receiving a PLAY request.
|
||||
func (sh *serverHandler) OnPlay(ctx *gortsplib.ServerHandlerOnPlayCtx) (*base.Response, error) {
|
||||
log.Printf("PLAY request")
|
||||
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusOK,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
h := &serverHandler{}
|
||||
|
||||
// prevent clients from connecting to the server until the stream is properly set up
|
||||
h.mutex.Lock()
|
||||
|
||||
// create the server
|
||||
h.server = &gortsplib.Server{
|
||||
Handler: h,
|
||||
RTSPAddress: ":8554",
|
||||
UDPRTPAddress: ":8000",
|
||||
UDPRTCPAddress: ":8001",
|
||||
MulticastIPRange: "224.1.0.0/16",
|
||||
MulticastRTPPort: 8002,
|
||||
MulticastRTCPPort: 8003,
|
||||
}
|
||||
|
||||
// start the server
|
||||
err := h.server.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer h.server.Close()
|
||||
|
||||
// create a RTSP description that contains a H264 format
|
||||
desc := &description.Session{
|
||||
Medias: []*description.Media{{
|
||||
Type: description.MediaTypeVideo,
|
||||
Formats: []format.Format{&format.H264{
|
||||
PayloadTyp: 96,
|
||||
PacketizationMode: 1,
|
||||
}},
|
||||
}},
|
||||
}
|
||||
|
||||
// create a server stream
|
||||
h.stream = &gortsplib.ServerStream{
|
||||
Server: h.server,
|
||||
Desc: desc,
|
||||
}
|
||||
err = h.stream.Initialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer h.stream.Close()
|
||||
|
||||
// create file streamer
|
||||
r := &fileStreamer{stream: h.stream}
|
||||
err = r.initialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer r.close()
|
||||
|
||||
// allow clients to connect
|
||||
h.mutex.Unlock()
|
||||
|
||||
// wait until a fatal error
|
||||
log.Printf("server is ready on %s", h.server.RTSPAddress)
|
||||
panic(h.server.Wait())
|
||||
}
|
@@ -15,9 +15,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. create a RTSP server which accepts plain connections
|
||||
// 2. allow a single client to publish a stream, containing a H264 media, with TCP or UDP
|
||||
// 3. save the content of the H264 media in a file in MPEG-TS format
|
||||
// 1. create a RTSP server which accepts plain connections.
|
||||
// 2. allow a single client to publish a stream, containing a H264 format.
|
||||
// 3. save the content of the H264 media in a file in MPEG-TS format.
|
||||
|
||||
type serverHandler struct {
|
||||
server *gortsplib.Server
|
@@ -34,7 +34,11 @@ func (e *mpegtsMuxer) initialize() error {
|
||||
Codec: &mpegts.CodecH264{},
|
||||
}
|
||||
|
||||
e.w = mpegts.NewWriter(e.b, []*mpegts.Track{e.track})
|
||||
e.w = &mpegts.Writer{W: e.b, Tracks: []*mpegts.Track{e.track}}
|
||||
err = e.w.Initialize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@@ -14,9 +14,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. create a RTSP server which accepts only connections encrypted with TLS (RTSPS)
|
||||
// 2. allow a single client to publish a stream with TCP
|
||||
// 3. allow multiple clients to read that stream with TCP
|
||||
// 1. create a RTSP server which accepts only connections encrypted with TLS (RTSPS).
|
||||
// 2. allow a single client to publish a stream with TCP.
|
||||
// 3. allow multiple clients to read the stream with TCP.
|
||||
|
||||
type serverHandler struct {
|
||||
server *gortsplib.Server
|
||||
|
@@ -13,9 +13,9 @@ import (
|
||||
)
|
||||
|
||||
// This example shows how to
|
||||
// 1. create a RTSP server which accepts plain connections
|
||||
// 2. allow a single client to publish a stream with TCP or UDP
|
||||
// 3. allow multiple clients to read that stream with TCP, UDP or UDP-multicast
|
||||
// 1. create a RTSP server which accepts plain connections.
|
||||
// 2. allow a single client to publish a stream with TCP or UDP.
|
||||
// 3. allow multiple clients to read the stream with TCP, UDP or UDP-multicast.
|
||||
|
||||
type serverHandler struct {
|
||||
server *gortsplib.Server
|
||||
|
Reference in New Issue
Block a user