mirror of https://github.com/q191201771/lal.git
1. [feat] 新增app/demo/calcrtmpdelay,可用于测量rtmp服务器的转发延时 2. [refactor] 重构app/demo/pullrtmp2pushrtmp的对象管理逻辑
parent
fd0f71f9af
commit
4a48518f5a
@ -0,0 +1,134 @@
|
||||
// Copyright 2021, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/lal
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/q191201771/lal/pkg/base"
|
||||
"github.com/q191201771/lal/pkg/httpflv"
|
||||
"github.com/q191201771/lal/pkg/remux"
|
||||
"github.com/q191201771/lal/pkg/rtmp"
|
||||
"github.com/q191201771/naza/pkg/nazalog"
|
||||
"github.com/q191201771/naza/pkg/nazamd5"
|
||||
)
|
||||
|
||||
const detailFilename = "delay.txt"
|
||||
|
||||
func main() {
|
||||
tagKey2writeTime := make(map[string]time.Time)
|
||||
var delays []int64
|
||||
var mu sync.Mutex
|
||||
|
||||
_ = nazalog.Init(func(option *nazalog.Option) {
|
||||
option.AssertBehavior = nazalog.AssertFatal
|
||||
})
|
||||
filename, pushURL, pullURL := parseFlag()
|
||||
|
||||
tags, err := httpflv.ReadAllTagsFromFLVFile(filename)
|
||||
nazalog.Assert(nil, err)
|
||||
nazalog.Infof("read tags from flv file succ. len of tags=%d", len(tags))
|
||||
|
||||
pushSession := rtmp.NewPushSession()
|
||||
err = pushSession.Push(pushURL)
|
||||
nazalog.Assert(nil, err)
|
||||
nazalog.Info("push succ.")
|
||||
//defer pushSession.Dispose()
|
||||
|
||||
pullSession := rtmp.NewPullSession()
|
||||
err = pullSession.Pull(pullURL, func(msg base.RTMPMsg) {
|
||||
tagKey := nazamd5.MD5(msg.Payload)
|
||||
mu.Lock()
|
||||
t, exist := tagKey2writeTime[tagKey]
|
||||
if !exist {
|
||||
nazalog.Errorf("tag key not exist.")
|
||||
} else {
|
||||
delay := time.Now().Sub(t).Milliseconds()
|
||||
delays = append(delays, delay)
|
||||
delete(tagKey2writeTime, tagKey)
|
||||
}
|
||||
mu.Unlock()
|
||||
})
|
||||
nazalog.Assert(nil, err)
|
||||
nazalog.Info("pull succ.")
|
||||
//defer pullSession.Dispose()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(5 * time.Second)
|
||||
pushSession.UpdateStat(1)
|
||||
pullSession.UpdateStat(1)
|
||||
nazalog.Debugf("stat bitrate. push=%+v, pull=%+v", pushSession.GetStat().Bitrate, pullSession.GetStat().Bitrate)
|
||||
}
|
||||
}()
|
||||
|
||||
prevTS := int64(-1)
|
||||
for _, tag := range tags {
|
||||
h := remux.FLVTagHeader2RTMPHeader(tag.Header)
|
||||
chunks := rtmp.Message2Chunks(tag.Raw[11:11+h.MsgLen], &h)
|
||||
|
||||
if prevTS >= 0 && int64(h.TimestampAbs) > prevTS {
|
||||
diff := int64(h.TimestampAbs) - prevTS
|
||||
time.Sleep(time.Duration(diff) * time.Millisecond)
|
||||
}
|
||||
prevTS = int64(h.TimestampAbs)
|
||||
|
||||
mu.Lock()
|
||||
tagKey := nazamd5.MD5(tag.Raw[11 : 11+h.MsgLen])
|
||||
if _, exist := tagKey2writeTime[tagKey]; exist {
|
||||
nazalog.Errorf("tag key already exist. key=%s", tagKey)
|
||||
}
|
||||
tagKey2writeTime[tagKey] = time.Now()
|
||||
mu.Unlock()
|
||||
|
||||
err = pushSession.AsyncWrite(chunks)
|
||||
nazalog.Assert(nil, err)
|
||||
//nazalog.Debugf("sent. %d", i)
|
||||
}
|
||||
|
||||
min := int64(2147483647)
|
||||
max := int64(0)
|
||||
avg := int64(0)
|
||||
sum := int64(0)
|
||||
fp, _ := os.Create(detailFilename)
|
||||
defer fp.Close()
|
||||
for _, d := range delays {
|
||||
if d < min {
|
||||
min = d
|
||||
}
|
||||
if d > max {
|
||||
max = d
|
||||
}
|
||||
sum += d
|
||||
_, _ = fp.WriteString(fmt.Sprintf("%d\n", d))
|
||||
}
|
||||
if len(delays) > 0 {
|
||||
avg = sum / int64(len(delays))
|
||||
}
|
||||
nazalog.Debugf("len(tagKey2writeTime)=%d, delays(len=%d, avg=%d, min=%d, max=%d), detailFilename=%s", len(tagKey2writeTime), len(delays), avg, min, max, detailFilename)
|
||||
}
|
||||
|
||||
func parseFlag() (filename, pushURL, pullURL string) {
|
||||
f := flag.String("f", "", "specify flv file")
|
||||
i := flag.String("i", "", "specify rtmp pull url")
|
||||
o := flag.String("o", "", "specify rtmp push url")
|
||||
flag.Parse()
|
||||
if *f == "" || *i == "" || *o == "" {
|
||||
flag.Usage()
|
||||
_, _ = fmt.Fprintf(os.Stderr, `Example:
|
||||
%s -f test.flv -i rtmp://127.0.0.1:1935/live/test -o rtmp://127.0.0.1:1935/live/test
|
||||
`, os.Args[0])
|
||||
base.OSExitAndWaitPressIfWindows(1)
|
||||
}
|
||||
return *f, *i, *o
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
{
|
||||
"rtmp": {
|
||||
"enable": true,
|
||||
"addr": ":1935",
|
||||
"gop_num": 0
|
||||
},
|
||||
"httpflv": {
|
||||
"enable": false,
|
||||
"sub_listen_addr": ":8080",
|
||||
"enable_https": false,
|
||||
"https_addr": ":4433",
|
||||
"https_cert_file": "./conf/cert.pem",
|
||||
"https_key_file": "./conf/key.pem",
|
||||
"gop_num": 0
|
||||
},
|
||||
"hls": {
|
||||
"enable": false,
|
||||
"sub_listen_addr": ":8081",
|
||||
"out_path": "/tmp/lal/hls/",
|
||||
"fragment_duration_ms": 3000,
|
||||
"fragment_num": 6,
|
||||
"cleanup_flag": true
|
||||
},
|
||||
"httpts": {
|
||||
"enable": false,
|
||||
"sub_listen_addr": ":8082"
|
||||
},
|
||||
"rtsp": {
|
||||
"enable": false,
|
||||
"addr": ":5544"
|
||||
},
|
||||
"relay_push": {
|
||||
"enable": false,
|
||||
"addr_list":[
|
||||
]
|
||||
},
|
||||
"relay_pull": {
|
||||
"enable": false,
|
||||
"addr": ""
|
||||
},
|
||||
"http_api": {
|
||||
"enable": false,
|
||||
"addr": ":8083"
|
||||
},
|
||||
"server_id": "1",
|
||||
"http_notify": {
|
||||
"enable": false,
|
||||
"update_interval_sec": 5,
|
||||
"on_server_start": "http://127.0.0.1:10101/on_server_start",
|
||||
"on_update": "http://127.0.0.1:10101/on_update",
|
||||
"on_pub_start": "http://127.0.0.1:10101/on_pub_start",
|
||||
"on_pub_stop": "http://127.0.0.1:10101/on_pub_stop",
|
||||
"on_sub_start": "http://127.0.0.1:10101/on_sub_start",
|
||||
"on_sub_stop": "http://127.0.0.1:10101/on_sub_stop",
|
||||
"on_rtmp_connect": "http://127.0.0.1:10101/on_rtmp_connect"
|
||||
},
|
||||
"pprof": {
|
||||
"enable": true,
|
||||
"addr": ":8084"
|
||||
},
|
||||
"log": {
|
||||
"level": 1,
|
||||
"filename": "./logs/lalserver.log",
|
||||
"is_to_stdout": true,
|
||||
"is_rotate_daily": true,
|
||||
"short_file_flag": true,
|
||||
"assert_behavior": 1
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
// Copyright 2021, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/lal
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package httpflv
|
||||
|
||||
import "io"
|
||||
|
||||
func ReadAllTagsFromFLVFile(filename string) ([]Tag, error) {
|
||||
var tags []Tag
|
||||
|
||||
var ffr FLVFileReader
|
||||
err := ffr.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for {
|
||||
tag, err := ffr.ReadTag()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return tags, nil
|
||||
} else {
|
||||
return tags, err
|
||||
}
|
||||
}
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
// never reach here
|
||||
}
|
Loading…
Reference in New Issue