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
131 lines (109 loc) · 2.93 KB
/
main.go
File metadata and controls
131 lines (109 loc) · 2.93 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
//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"
"github.com/bluenviron/mediacommon/v2/pkg/codecs/mpeg4audio"
)
// 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.
// This example requires the FFmpeg libraries, that can be installed with this command:
// apt install -y libavcodec-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 description that contains a MPEG-4 Audio format
forma := &format.MPEG4Audio{
PayloadTyp: 96,
Config: &mpeg4audio.Config{
Type: mpeg4audio.ObjectTypeAACLC,
SampleRate: 48000,
ChannelCount: 1,
},
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
}
desc := &description.Session{
Medias: []*description.Media{{
Type: description.MediaTypeAudio,
Formats: []format.Format{forma},
}},
}
// connect to the server and start recording
c := gortsplib.Client{}
err := c.StartRecording("rtsp://myuser:mypass@localhost:8554/mystream", desc)
if err != nil {
panic(err)
}
defer c.Close()
// setup LPCM -> MPEG-4 Audio encoder
mp4aEnc := &mp4aEncoder{}
err = mp4aEnc.initialize()
if err != nil {
panic(err)
}
defer mp4aEnc.close()
// setup MPEG-4 Audio -> RTP encoder
rtpEnc, err := forma.CreateEncoder()
if err != nil {
panic(err)
}
start := time.Now()
prevPTS := int64(0)
randomStart, err := randUint32()
if err != nil {
panic(err)
}
// setup a ticker to sleep between writings
ticker := time.NewTicker(100 * time.Millisecond)
defer ticker.Stop()
for range ticker.C {
// get current timestamp
pts := multiplyAndDivide(int64(time.Since(start)), int64(forma.ClockRate()), int64(time.Second))
// generate dummy LPCM audio samples
samples := createDummyAudio(pts, prevPTS)
// encode samples with MPEG-4 Audio
aus, outPTS, err := mp4aEnc.encode(samples)
if err != nil {
panic(err)
}
if aus == nil {
continue
}
// generate RTP packets from MPEG-4 audio access units
pkts, err := rtpEnc.Encode(aus)
if err != nil {
panic(err)
}
log.Printf("writing RTP packets with PTS=%d, packet count=%d", outPTS, len(pkts))
for _, pkt := range pkts {
pkt.Timestamp += uint32(int64(randomStart) + outPTS)
err = c.WritePacketRTP(desc.Medias[0], pkt)
if err != nil {
panic(err)
}
}
prevPTS = pts
}
}