-
Notifications
You must be signed in to change notification settings - Fork 198
/
main.go
146 lines (123 loc) · 3.06 KB
/
main.go
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
138
139
140
141
142
143
144
145
146
package main
import (
"log"
"github.com/bluenviron/gortsplib/v4"
"github.com/bluenviron/gortsplib/v4/pkg/base"
"github.com/bluenviron/gortsplib/v4/pkg/format"
"github.com/bluenviron/gortsplib/v4/pkg/format/rtph264"
"github.com/pion/rtp"
)
// This example shows how to
// 1. connect to a RTSP server
// 2. check if there's a H264 format and an MPEG-4 audio format
// 3. save the content of those formats in a file in MPEG-TS format
func main() {
c := gortsplib.Client{}
// parse URL
u, err := base.ParseURL("rtsp://localhost:8554/stream")
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 available medias
desc, _, err := c.Describe(u)
if err != nil {
panic(err)
}
// find the H264 media and format
var h264Format *format.H264
h264Media := desc.FindFormat(&h264Format)
if h264Media == nil {
panic("H264 media not found")
}
// find the MPEG-4 audio media and format
var mpeg4AudioFormat *format.MPEG4Audio
mpeg4AudioMedia := desc.FindFormat(&mpeg4AudioFormat)
if mpeg4AudioMedia == nil {
panic("MPEG-4 audio media not found")
}
// setup RTP -> H264 decoder
h264RTPDec, err := h264Format.CreateDecoder()
if err != nil {
panic(err)
}
// setup RTP -> MPEG-4 audio decoder
mpeg4AudioRTPDec, err := mpeg4AudioFormat.CreateDecoder()
if err != nil {
panic(err)
}
// setup MPEG-TS muxer
mpegtsMuxer := &mpegtsMuxer{
fileName: "mystream.ts",
h264Format: h264Format,
mpeg4AudioFormat: mpeg4AudioFormat,
}
err = mpegtsMuxer.initialize()
if err != nil {
panic(err)
}
defer mpegtsMuxer.close()
// setup all medias
err = c.SetupAll(desc.BaseURL, desc.Medias)
if err != nil {
panic(err)
}
// called when a H264/RTP packet arrives
c.OnPacketRTP(h264Media, h264Format, func(pkt *rtp.Packet) {
// decode timestamp
pts, ok := c.PacketPTS2(h264Media, pkt)
if !ok {
log.Printf("waiting for timestamp")
return
}
// extract access unit from RTP packets
au, err := h264RTPDec.Decode(pkt)
if err != nil {
if err != rtph264.ErrNonStartingPacketAndNoPrevious && err != rtph264.ErrMorePacketsNeeded {
log.Printf("ERR: %v", err)
}
return
}
// encode the access unit into MPEG-TS
err = mpegtsMuxer.writeH264(au, pts)
if err != nil {
log.Printf("ERR: %v", err)
return
}
log.Printf("saved TS packet")
})
// called when a MPEG-4 audio / RTP packet arrives
c.OnPacketRTP(mpeg4AudioMedia, mpeg4AudioFormat, func(pkt *rtp.Packet) {
// decode timestamp
pts, ok := c.PacketPTS2(mpeg4AudioMedia, pkt)
if !ok {
log.Printf("waiting for timestamp")
return
}
// extract access units from RTP packets
aus, err := mpeg4AudioRTPDec.Decode(pkt)
if err != nil {
log.Printf("ERR: %v", err)
return
}
// encode access units into MPEG-TS
err = mpegtsMuxer.writeMPEG4Audio(aus, pts)
if err != nil {
log.Printf("ERR: %v", err)
return
}
log.Printf("saved TS packet")
})
// start playing
_, err = c.Play(nil)
if err != nil {
panic(err)
}
// wait until a fatal error
panic(c.Wait())
}