forked from bluenviron/gortsplib
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
137 lines (114 loc) · 3.01 KB
/
main.go
File metadata and controls
137 lines (114 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//go:build cgo
// Package main contains an example.
package main
import (
"crypto/rand"
"log"
"time"
"github.com/bluenviron/gortsplib/v5"
"github.com/bluenviron/gortsplib/v5/pkg/description"
"github.com/bluenviron/gortsplib/v5/pkg/format"
)
// 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.
// This example requires the FFmpeg libraries, that can be installed with this command:
// apt install -y libavcodec-dev libswscale-dev gcc pkg-config
func multiplyAndDivide(v, m, d int64) int64 {
secs := v / d
dec := v % d
return (secs*m + dec*m/d)
}
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 main() {
// create a stream description that contains a H264 format
forma := &format.H264{
PayloadTyp: 96,
PacketizationMode: 1,
}
desc := &description.Session{
Medias: []*description.Media{{
Type: description.MediaTypeVideo,
Formats: []format.Format{forma},
}},
}
// Client allows to set additional client options
c := &gortsplib.Client{
// transport protocol (UDP or TCP). If nil, it is chosen automatically
Protocol: nil,
// timeout of read operations
ReadTimeout: 10 * time.Second,
// timeout of write operations
WriteTimeout: 10 * time.Second,
}
// connect to the server, announce the format and start recording
err := c.StartRecording("rtsp://myuser:mypass@localhost:8554/mystream", desc)
if err != nil {
panic(err)
}
defer c.Close()
// setup RGBA -> H264 encoder
h264enc := &h264Encoder{
Width: 640,
Height: 480,
FPS: 5,
}
err = h264enc.initialize()
if err != nil {
panic(err)
}
defer h264enc.close()
// setup H264 -> RTP encoder
rtpEnc, err := forma.CreateEncoder()
if err != nil {
panic(err)
}
start := time.Now()
randomStart, err := randUint32()
if err != nil {
panic(err)
}
// setup a ticker to sleep between frames
ticker := time.NewTicker(200 * time.Millisecond)
defer ticker.Stop()
for range ticker.C {
// get current timestamp
pts := multiplyAndDivide(int64(time.Since(start)), int64(forma.ClockRate()), int64(time.Second))
// create a dummy image
img := createDummyImage()
// encode the image with H264
au, pts, err := h264enc.encode(img, pts)
if err != nil {
panic(err)
}
// wait for a H264 access unit
if au == nil {
continue
}
// generate RTP packets from the H264 access unit
pkts, err := rtpEnc.Encode(au)
if err != nil {
panic(err)
}
log.Printf("writing RTP packets with PTS=%d, au=%d, pkts=%d", pts, len(au), len(pkts))
// write RTP packets to the server
for _, pkt := range pkts {
pkt.Timestamp += uint32(int64(randomStart) + pts)
err = c.WritePacketRTP(desc.Medias[0], pkt)
if err != nil {
panic(err)
}
}
}
}