You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/rtmp/client_pull_session.go

174 lines
5.8 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// Copyright 2019, 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 rtmp
import (
"crypto/tls"
"github.com/q191201771/lal/pkg/base"
)
type OnReadRtmpAvMsg func(msg base.RtmpMsg)
type PullSession struct {
core *ClientSession
}
type PullSessionOption struct {
// PullTimeoutMs
//
// 从调用Pull函数到接收音视频数据的前一步也即收到服务端返回的rtmp play对应结果的信令的超时时间
// 如果为0则没有超时时间
//
PullTimeoutMs int
ReadAvTimeoutMs int
ReadBufSize int // io层读取音视频数据时的缓冲大小如果为0则没有缓冲
ReuseReadMessageBufferFlag bool // 接收Message时是否复用内存块
PeerWinAckSize int
HandshakeComplexFlag bool
// TlsConfig
// rtmps时使用。
// 不关心可以不填。
// 业务方可以通过这个字段自定义 tls.Config
// 注意如果使用rtmps并且该字段为nil那么内部会使用 base.DefaultTlsConfigClient 生成 tls.Config
TlsConfig *tls.Config
}
var defaultPullSessionOption = PullSessionOption{
PullTimeoutMs: 10000,
ReadAvTimeoutMs: 0,
ReadBufSize: 0,
HandshakeComplexFlag: false,
PeerWinAckSize: 0,
ReuseReadMessageBufferFlag: true,
}
type ModPullSessionOption func(option *PullSessionOption)
func NewPullSession(modOptions ...ModPullSessionOption) *PullSession {
opt := defaultPullSessionOption
for _, fn := range modOptions {
fn(&opt)
}
return &PullSession{
core: NewClientSession(base.SessionTypeRtmpPull, func(option *ClientSessionOption) {
option.DoTimeoutMs = opt.PullTimeoutMs
option.ReadAvTimeoutMs = opt.ReadAvTimeoutMs
option.ReadBufSize = opt.ReadBufSize
option.HandshakeComplexFlag = opt.HandshakeComplexFlag
option.PeerWinAckSize = opt.PeerWinAckSize
option.ReuseReadMessageBufferFlag = opt.ReuseReadMessageBufferFlag
}),
}
}
// WithOnPullSucc Pull成功
//
// 如果你想保证绝对时序,在 WithOnReadRtmpAvMsg 回调音视频数据前,做一些操作,那么使用这个回调替代 Start 返回成功
func (s *PullSession) WithOnPullSucc(onPullResult func()) *PullSession {
s.core.onDoResult = onPullResult
return s
}
// WithOnReadRtmpAvMsg
//
// @param onReadRtmpAvMsg:
//
// msg: 关于内存块的说明:
// ReuseReadMessageBufferFlag 为true时
// 回调结束后,`msg`的内存块会被`PullSession`重复使用。
// 也即多次回调的`msg`是复用的同一块内存块。
// 如果业务方需要在回调结束后,依然持有`msg`,那么需要对`msg`进行拷贝,比如调用`msg.Clone()`。
// 只在回调中使用`msg`,则不需要拷贝。
// ReuseReadMessageBufferFlag 为false时
// 回调接收后,`PullSession`不再使用该内存块。
// 业务方可以自由持有释放该内存块。
func (s *PullSession) WithOnReadRtmpAvMsg(onReadRtmpAvMsg OnReadRtmpAvMsg) *PullSession {
s.core.onReadRtmpAvMsg = onReadRtmpAvMsg
return s
}
// Start 阻塞直到和对端完成拉流前的所有准备工作也即收到RTMP Play response或者发生错误
func (s *PullSession) Start(rawUrl string) error {
return s.core.Start(rawUrl)
}
// Pull deprecated. use Start instead.
func (s *PullSession) Pull(rawUrl string) error {
return s.Start(rawUrl)
}
// ---------------------------------------------------------------------------------------------------------------------
// IClientSessionLifecycle interface
// ---------------------------------------------------------------------------------------------------------------------
// Dispose 文档请参考: IClientSessionLifecycle interface
func (s *PullSession) Dispose() error {
return s.core.Dispose()
}
// WaitChan 文档请参考: IClientSessionLifecycle interface
func (s *PullSession) WaitChan() <-chan error {
return s.core.WaitChan()
}
// ---------------------------------------------------------------------------------------------------------------------
// ISessionUrlContext interface
// ---------------------------------------------------------------------------------------------------------------------
// Url 文档请参考: interface ISessionUrlContext
func (s *PullSession) Url() string {
return s.core.Url()
}
// AppName 文档请参考: interface ISessionUrlContext
func (s *PullSession) AppName() string {
return s.core.AppName()
}
// StreamName 文档请参考: interface ISessionUrlContext
func (s *PullSession) StreamName() string {
return s.core.StreamName()
}
// RawQuery 文档请参考: interface ISessionUrlContext
func (s *PullSession) RawQuery() string {
return s.core.RawQuery()
}
// ---------------------------------------------------------------------------------------------------------------------
// IObject interface
// ---------------------------------------------------------------------------------------------------------------------
// UniqueKey 文档请参考: interface IObject
func (s *PullSession) UniqueKey() string {
return s.core.UniqueKey()
}
// ---------------------------------------------------------------------------------------------------------------------
// ISessionStat interface
// ---------------------------------------------------------------------------------------------------------------------
// GetStat 文档请参考: interface ISessionStat
func (s *PullSession) GetStat() base.StatSession {
return s.core.GetStat()
}
// UpdateStat 文档请参考: interface ISessionStat
func (s *PullSession) UpdateStat(intervalSec uint32) {
s.core.UpdateStat(intervalSec)
}
// IsAlive 文档请参考: interface ISessionStat
func (s *PullSession) IsAlive() (readAlive, writeAlive bool) {
return s.core.IsAlive()
}