mirror of https://github.com/q191201771/lal.git
1. [refactor] 重构logic.Group 2. [test] 修复CI环境的innertest
parent
c3314bc7d2
commit
8c0d272fad
@ -0,0 +1,57 @@
|
||||
// Copyright 2022, 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 logic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/q191201771/lal/pkg/httpflv"
|
||||
)
|
||||
|
||||
// startRecordFlvIfNeeded 必要时开启flv录制
|
||||
//
|
||||
func (group *Group) startRecordFlvIfNeeded(nowUnix int64) {
|
||||
if !group.config.RecordConfig.EnableFlv {
|
||||
return
|
||||
}
|
||||
|
||||
// 构造文件名
|
||||
filename := fmt.Sprintf("%s-%d.flv", group.streamName, nowUnix)
|
||||
filenameWithPath := filepath.Join(group.config.RecordConfig.FlvOutPath, filename)
|
||||
// 如果已经在录制,则先关闭
|
||||
// TODO(chef): 正常的逻辑是否会走到这?
|
||||
if group.recordFlv != nil {
|
||||
Log.Errorf("[%s] record flv but already exist. new filename=%s, old filename=%s",
|
||||
group.UniqueKey, filenameWithPath, group.recordFlv.Name())
|
||||
_ = group.recordFlv.Dispose()
|
||||
}
|
||||
// 初始化录制
|
||||
group.recordFlv = &httpflv.FlvFileWriter{}
|
||||
if err := group.recordFlv.Open(filenameWithPath); err != nil {
|
||||
Log.Errorf("[%s] record flv open file failed. filename=%s, err=%+v",
|
||||
group.UniqueKey, filenameWithPath, err)
|
||||
group.recordFlv = nil
|
||||
}
|
||||
if err := group.recordFlv.WriteFlvHeader(); err != nil {
|
||||
Log.Errorf("[%s] record flv write flv header failed. filename=%s, err=%+v",
|
||||
group.UniqueKey, filenameWithPath, err)
|
||||
group.recordFlv = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (group *Group) stopRecordFlvIfNeeded() {
|
||||
if !group.config.RecordConfig.EnableFlv {
|
||||
return
|
||||
}
|
||||
if group.recordFlv != nil {
|
||||
_ = group.recordFlv.Dispose()
|
||||
group.recordFlv = nil
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
// Copyright 2022, 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 logic
|
||||
|
||||
import "github.com/q191201771/lal/pkg/hls"
|
||||
|
||||
func (group *Group) IsHlsMuxerAlive() bool {
|
||||
group.mutex.Lock()
|
||||
defer group.mutex.Unlock()
|
||||
return group.hlsMuxer != nil
|
||||
}
|
||||
|
||||
// startHlsIfNeeded 必要时启动hls
|
||||
//
|
||||
func (group *Group) startHlsIfNeeded() {
|
||||
// TODO(chef): [refactor] ts依赖hls
|
||||
if !group.config.HlsConfig.Enable {
|
||||
return
|
||||
}
|
||||
if group.hlsMuxer != nil {
|
||||
Log.Errorf("[%s] hls muxer exist while addIn. muxer=%+v", group.UniqueKey, group.hlsMuxer)
|
||||
}
|
||||
enable := group.config.HlsConfig.Enable || group.config.HlsConfig.EnableHttps
|
||||
group.hlsMuxer = hls.NewMuxer(group.streamName, enable, &group.config.HlsConfig.MuxerConfig, group)
|
||||
group.hlsMuxer.Start()
|
||||
}
|
||||
|
||||
func (group *Group) stopHlsIfNeeded() {
|
||||
if !group.config.HlsConfig.Enable {
|
||||
return
|
||||
}
|
||||
if group.hlsMuxer != nil {
|
||||
group.hlsMuxer.Dispose()
|
||||
group.observer.CleanupHlsIfNeeded(group.appName, group.streamName, group.hlsMuxer.OutPath())
|
||||
group.hlsMuxer = nil
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
// Copyright 2022, 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 logic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/q191201771/lal/pkg/mpegts"
|
||||
)
|
||||
|
||||
// startRecordMpegtsIfNeeded 必要时开启ts录制
|
||||
//
|
||||
func (group *Group) startRecordMpegtsIfNeeded(nowUnix int64) {
|
||||
if !group.config.RecordConfig.EnableMpegts {
|
||||
return
|
||||
}
|
||||
|
||||
// 构造文件名
|
||||
filename := fmt.Sprintf("%s-%d.ts", group.streamName, nowUnix)
|
||||
filenameWithPath := filepath.Join(group.config.RecordConfig.MpegtsOutPath, filename)
|
||||
// 如果已经在录制,则先关闭
|
||||
if group.recordMpegts != nil {
|
||||
Log.Errorf("[%s] record mpegts but already exist. new filename=%s, old filename=%s",
|
||||
group.UniqueKey, filenameWithPath, group.recordMpegts.Name())
|
||||
_ = group.recordMpegts.Dispose()
|
||||
}
|
||||
group.recordMpegts = &mpegts.FileWriter{}
|
||||
if err := group.recordMpegts.Create(filenameWithPath); err != nil {
|
||||
Log.Errorf("[%s] record mpegts open file failed. filename=%s, err=%+v",
|
||||
group.UniqueKey, filenameWithPath, err)
|
||||
group.recordMpegts = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (group *Group) stopRecordMpegtsIfNeeded() {
|
||||
if !group.config.RecordConfig.EnableMpegts {
|
||||
return
|
||||
}
|
||||
if group.recordMpegts != nil {
|
||||
_ = group.recordMpegts.Dispose()
|
||||
group.recordMpegts = nil
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
// Copyright 2022, 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 logic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/q191201771/lal/pkg/rtmp"
|
||||
)
|
||||
|
||||
func (group *Group) AddRtmpPushSession(url string, session *rtmp.PushSession) {
|
||||
Log.Debugf("[%s] [%s] add rtmp PushSession into group.", group.UniqueKey, session.UniqueKey())
|
||||
group.mutex.Lock()
|
||||
defer group.mutex.Unlock()
|
||||
if group.url2PushProxy != nil {
|
||||
group.url2PushProxy[url].pushSession = session
|
||||
}
|
||||
}
|
||||
|
||||
func (group *Group) DelRtmpPushSession(url string, session *rtmp.PushSession) {
|
||||
Log.Debugf("[%s] [%s] del rtmp PushSession into group.", group.UniqueKey, session.UniqueKey())
|
||||
group.mutex.Lock()
|
||||
defer group.mutex.Unlock()
|
||||
if group.url2PushProxy != nil {
|
||||
group.url2PushProxy[url].pushSession = nil
|
||||
group.url2PushProxy[url].isPushing = false
|
||||
}
|
||||
}
|
||||
|
||||
type pushProxy struct {
|
||||
isPushing bool
|
||||
pushSession *rtmp.PushSession
|
||||
}
|
||||
|
||||
func (group *Group) initRelayPush() {
|
||||
enable := group.config.RelayPushConfig.Enable
|
||||
addrList := group.config.RelayPushConfig.AddrList
|
||||
appName := group.appName
|
||||
streamName := group.streamName
|
||||
|
||||
url2PushProxy := make(map[string]*pushProxy)
|
||||
if enable {
|
||||
for _, addr := range addrList {
|
||||
pushUrl := fmt.Sprintf("rtmp://%s/%s/%s", addr, appName, streamName)
|
||||
url2PushProxy[pushUrl] = &pushProxy{
|
||||
isPushing: false,
|
||||
pushSession: nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group.pushEnable = group.config.RelayPushConfig.Enable
|
||||
group.url2PushProxy = url2PushProxy
|
||||
}
|
||||
|
||||
// startPushIfNeeded 必要时进行replay push转推
|
||||
//
|
||||
func (group *Group) startPushIfNeeded() {
|
||||
// push转推功能没开
|
||||
if !group.pushEnable {
|
||||
return
|
||||
}
|
||||
// 没有pub发布者
|
||||
if group.rtmpPubSession == nil && group.rtspPubSession == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// relay push时携带rtmp pub的参数
|
||||
// TODO chef: 这个逻辑放这里不太好看
|
||||
var urlParam string
|
||||
if group.rtmpPubSession != nil {
|
||||
urlParam = group.rtmpPubSession.RawQuery()
|
||||
}
|
||||
|
||||
for url, v := range group.url2PushProxy {
|
||||
// 正在转推中
|
||||
if v.isPushing {
|
||||
continue
|
||||
}
|
||||
v.isPushing = true
|
||||
|
||||
urlWithParam := url
|
||||
if urlParam != "" {
|
||||
urlWithParam += "?" + urlParam
|
||||
}
|
||||
Log.Infof("[%s] start relay push. url=%s", group.UniqueKey, urlWithParam)
|
||||
|
||||
go func(u, u2 string) {
|
||||
pushSession := rtmp.NewPushSession(func(option *rtmp.PushSessionOption) {
|
||||
option.PushTimeoutMs = relayPushTimeoutMs
|
||||
option.WriteAvTimeoutMs = relayPushWriteAvTimeoutMs
|
||||
})
|
||||
err := pushSession.Push(u2)
|
||||
if err != nil {
|
||||
Log.Errorf("[%s] relay push done. err=%v", pushSession.UniqueKey(), err)
|
||||
group.DelRtmpPushSession(u, pushSession)
|
||||
return
|
||||
}
|
||||
group.AddRtmpPushSession(u, pushSession)
|
||||
err = <-pushSession.WaitChan()
|
||||
Log.Infof("[%s] relay push done. err=%v", pushSession.UniqueKey(), err)
|
||||
group.DelRtmpPushSession(u, pushSession)
|
||||
}(url, urlWithParam)
|
||||
}
|
||||
}
|
||||
|
||||
func (group *Group) stopPushIfNeeded() {
|
||||
if !group.pushEnable {
|
||||
return
|
||||
}
|
||||
for _, v := range group.url2PushProxy {
|
||||
if v.pushSession != nil {
|
||||
v.pushSession.Dispose()
|
||||
}
|
||||
v.pushSession = nil
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue