Skip to content

Commit 2979d3f

Browse files
authored
Merge pull request #111 from chaymankala/master
Added Dial function for Replay stream
2 parents b6b1f4a + 3c1eaad commit 2979d3f

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

format/rtspv2/client.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,146 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) {
247247
return client, nil
248248
}
249249

250+
func ReplayDial(options RTSPClientOptions, startTime string) (*RTSPClient, error) {
251+
client := &RTSPClient{
252+
headers: make(map[string]string),
253+
Signals: make(chan int, 100),
254+
OutgoingProxyQueue: make(chan *[]byte, 3000),
255+
OutgoingPacketQueue: make(chan *av.Packet, 3000),
256+
BufferRtpPacket: bytes.NewBuffer([]byte{}),
257+
videoID: -1,
258+
audioID: -2,
259+
videoIDX: -1,
260+
audioIDX: -2,
261+
options: options,
262+
AudioTimeScale: 8000,
263+
}
264+
client.headers["User-Agent"] = "Lavf58.76.100"
265+
err := client.parseURL(html.UnescapeString(client.options.URL))
266+
if err != nil {
267+
return nil, err
268+
}
269+
conn, err := net.DialTimeout("tcp", client.pURL.Host, client.options.DialTimeout)
270+
if err != nil {
271+
return nil, err
272+
}
273+
err = conn.SetDeadline(time.Now().Add(client.options.ReadWriteTimeout))
274+
if err != nil {
275+
return nil, err
276+
}
277+
if client.pURL.Scheme == "rtsps" {
278+
tlsConn := tls.Client(conn, &tls.Config{InsecureSkipVerify: options.InsecureSkipVerify, ServerName: client.pURL.Hostname()})
279+
err = tlsConn.Handshake()
280+
if err != nil {
281+
return nil, err
282+
}
283+
conn = tlsConn
284+
}
285+
client.conn = conn
286+
client.connRW = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
287+
err = client.request(OPTIONS, nil, client.pURL.String(), false, false)
288+
if err != nil {
289+
return nil, err
290+
}
291+
err = client.request(DESCRIBE, map[string]string{"Accept": "application/sdp"}, client.pURL.String(), false, false)
292+
if err != nil {
293+
return nil, err
294+
}
295+
for _, i2 := range client.mediaSDP {
296+
if (i2.AVType != VIDEO && i2.AVType != AUDIO) || (client.options.DisableAudio && i2.AVType == AUDIO) {
297+
//TODO check it
298+
if strings.Contains(string(client.SDPRaw), "LaunchDigital") {
299+
client.chTMP += 2
300+
}
301+
continue
302+
}
303+
// err = client.request(SETUP, map[string]string{"Require": "onvif-replay", "Transport": "RTP/UDP"}, client.ControlTrack(i2.Control), false, false)
304+
err = client.request(SETUP, map[string]string{"Require": "onvif-replay", "Transport": "RTP/AVP/TCP;unicast;interleaved=" + strconv.Itoa(client.chTMP) + "-" + strconv.Itoa(client.chTMP+1)}, client.ControlTrack(i2.Control), false, false)
305+
if err != nil {
306+
return nil, err
307+
}
308+
if i2.AVType == VIDEO {
309+
if i2.Type == av.H264 {
310+
if len(i2.SpropParameterSets) > 1 {
311+
if codecData, err := h264parser.NewCodecDataFromSPSAndPPS(i2.SpropParameterSets[0], i2.SpropParameterSets[1]); err == nil {
312+
client.sps = i2.SpropParameterSets[0]
313+
client.pps = i2.SpropParameterSets[1]
314+
client.CodecData = append(client.CodecData, codecData)
315+
}
316+
} else {
317+
client.CodecData = append(client.CodecData, h264parser.CodecData{})
318+
client.WaitCodec = true
319+
}
320+
client.FPS = i2.FPS
321+
client.videoCodec = av.H264
322+
} else if i2.Type == av.H265 {
323+
if len(i2.SpropVPS) > 1 && len(i2.SpropSPS) > 1 && len(i2.SpropPPS) > 1 {
324+
if codecData, err := h265parser.NewCodecDataFromVPSAndSPSAndPPS(i2.SpropVPS, i2.SpropSPS, i2.SpropPPS); err == nil {
325+
client.vps = i2.SpropVPS
326+
client.sps = i2.SpropSPS
327+
client.pps = i2.SpropPPS
328+
client.CodecData = append(client.CodecData, codecData)
329+
}
330+
} else {
331+
client.CodecData = append(client.CodecData, h265parser.CodecData{})
332+
}
333+
client.videoCodec = av.H265
334+
335+
} else {
336+
client.Println("SDP Video Codec Type Not Supported", i2.Type)
337+
}
338+
client.videoIDX = int8(len(client.CodecData) - 1)
339+
client.videoID = client.chTMP
340+
}
341+
if i2.AVType == AUDIO {
342+
client.audioID = client.chTMP
343+
var CodecData av.AudioCodecData
344+
switch i2.Type {
345+
case av.AAC:
346+
CodecData, err = aacparser.NewCodecDataFromMPEG4AudioConfigBytes(i2.Config)
347+
if err == nil {
348+
client.Println("Audio AAC bad config")
349+
}
350+
case av.OPUS:
351+
var cl av.ChannelLayout
352+
switch i2.ChannelCount {
353+
case 1:
354+
cl = av.CH_MONO
355+
case 2:
356+
cl = av.CH_STEREO
357+
default:
358+
cl = av.CH_MONO
359+
}
360+
CodecData = codec.NewOpusCodecData(i2.TimeScale, cl)
361+
case av.PCM_MULAW:
362+
CodecData = codec.NewPCMMulawCodecData()
363+
case av.PCM_ALAW:
364+
CodecData = codec.NewPCMAlawCodecData()
365+
case av.PCM:
366+
CodecData = codec.NewPCMCodecData()
367+
default:
368+
client.Println("Audio Codec", i2.Type, "not supported")
369+
}
370+
if CodecData != nil {
371+
client.CodecData = append(client.CodecData, CodecData)
372+
client.audioIDX = int8(len(client.CodecData) - 1)
373+
client.audioCodec = CodecData.Type()
374+
if i2.TimeScale != 0 {
375+
client.AudioTimeScale = int64(i2.TimeScale)
376+
}
377+
}
378+
}
379+
client.chTMP += 2
380+
}
381+
test := map[string]string{"Require": "onvif-replay", "Scale": "1.000000", "Speed": "1.000000", "Range": "clock=" + startTime + "-"}
382+
err = client.request(PLAY, test, client.control, false, false)
383+
if err != nil {
384+
return nil, err
385+
}
386+
go client.startStream()
387+
return client, nil
388+
}
389+
250390
func (client *RTSPClient) ControlTrack(track string) string {
251391
if strings.Contains(track, "rtsp://") {
252392
return track

0 commit comments

Comments
 (0)