Documentation ¶
Index ¶
- Variables
- func FlvTag2RtmpChunks(tag httpflv.Tag) []byte
- func FlvTag2RtmpMsg(tag httpflv.Tag) (msg base.RtmpMsg)
- func FlvTagHeader2RtmpHeader(in httpflv.TagHeader) (out base.RtmpHeader)
- func MakeDefaultRtmpHeader(in base.RtmpHeader) (out base.RtmpHeader)
- func RtmpMsg2FlvTag(msg base.RtmpMsg) *httpflv.Tag
- type AvPacket2RtmpRemuxer
- func (r *AvPacket2RtmpRemuxer) FeedAvPacket(pkt base.AvPacket)
- func (r *AvPacket2RtmpRemuxer) InitWithAvConfig(asc, vps, sps, pps []byte)
- func (r *AvPacket2RtmpRemuxer) OnAvPacket(pkt base.AvPacket)
- func (r *AvPacket2RtmpRemuxer) OnRtpPacket(pkt rtprtcp.RtpPacket)
- func (r *AvPacket2RtmpRemuxer) OnSdp(sdpCtx sdp.LogicContext)
- func (r *AvPacket2RtmpRemuxer) WithOnRtmpMsg(onRtmpMsg rtmp.OnReadRtmpAvMsg) *AvPacket2RtmpRemuxer
- func (r *AvPacket2RtmpRemuxer) WithOption(modOption func(option *base.AvPacketStreamOption))
- type DummyAudioFilter
- type Gop
- type GopCache
- type GopCacheMpegts
- type GopMpegts
- type IRtmp2MpegtsRemuxerObserver
- type LazyGet
- type LazyRtmpChunkDivider
- type LazyRtmpMsg2FlvTag
- type OnRtpPacket
- type OnSdp
- type Rtmp2AvPacketRemuxer
- func (r *Rtmp2AvPacketRemuxer) FeedRtmpMsg(msg base.RtmpMsg, arg interface{}) error
- func (r *Rtmp2AvPacketRemuxer) WithOnAvPacket(onAvPacket func(pkt base.AvPacket, arg interface{})) *Rtmp2AvPacketRemuxer
- func (r *Rtmp2AvPacketRemuxer) WithOption(modOption func(option *Rtmp2AvPacketRemuxerOption)) *Rtmp2AvPacketRemuxer
- type Rtmp2AvPacketRemuxerOption
- type Rtmp2MpegtsRemuxer
- type Rtmp2MpegtsTimestampFilter
- type Rtmp2RtspRemuxer
Constants ¶
This section is empty.
Variables ¶
var ( Log = nazalog.GetGlobalLogger() // RtspRemuxerAddSpsPps2KeyFrameFlag https://github.com/ysjhlnu/lal/issues/205 // RtspRemuxerAddSpsPps2KeyFrameFlag = false )
Functions ¶
func FlvTag2RtmpChunks ¶
FlvTag2RtmpChunks @return 返回的内存块为内部新申请
func FlvTag2RtmpMsg ¶
FlvTag2RtmpMsg @return msg: 返回的内存块引用参数`tag`的内存块
func FlvTagHeader2RtmpHeader ¶
func FlvTagHeader2RtmpHeader(in httpflv.TagHeader) (out base.RtmpHeader)
func MakeDefaultRtmpHeader ¶
func MakeDefaultRtmpHeader(in base.RtmpHeader) (out base.RtmpHeader)
MakeDefaultRtmpHeader
使用场景:一般是输入流转换为输出流时。 目的:使得流格式更标准。 做法:设置 MsgStreamId 和 Csid,其他字段保持`in`的值。
Types ¶
type AvPacket2RtmpRemuxer ¶
type AvPacket2RtmpRemuxer struct {
// contains filtered or unexported fields
}
AvPacket2RtmpRemuxer AvPacket转换为RTMP
目前AvPacket来自:
- RTSP: sdp以及rtp的合帧包 - gb28181 ps: rtp的合帧包 - customize: 业务方通过接口向lalserver输入的流 - 理论上也支持webrtc,后续接入webrtc时再验证
func NewAvPacket2RtmpRemuxer ¶
func NewAvPacket2RtmpRemuxer() *AvPacket2RtmpRemuxer
func (*AvPacket2RtmpRemuxer) FeedAvPacket ¶
func (r *AvPacket2RtmpRemuxer) FeedAvPacket(pkt base.AvPacket)
FeedAvPacket
输入 base.AvPacket 数据
@param pkt:
- 如果是aac,格式是裸数据或带adts头,具体取决于前面的配置。
- 如果是h264,格式是avcc或Annexb,具体取决于前面的配置。 内部不持有该内存块。
func (*AvPacket2RtmpRemuxer) InitWithAvConfig ¶
func (r *AvPacket2RtmpRemuxer) InitWithAvConfig(asc, vps, sps, pps []byte)
InitWithAvConfig rtsp场景下,有时sps、pps等信息只包含在sdp中,有时包含在rtp包中, 这里提供输入sdp的sps、pps等信息的机会,如果没有,可以不调用
内部不持有输入参数的内存块
func (*AvPacket2RtmpRemuxer) OnAvPacket ¶
func (r *AvPacket2RtmpRemuxer) OnAvPacket(pkt base.AvPacket)
func (*AvPacket2RtmpRemuxer) OnRtpPacket ¶
func (r *AvPacket2RtmpRemuxer) OnRtpPacket(pkt rtprtcp.RtpPacket)
OnRtpPacket OnSdp OnAvPacket
实现RTSP回调数据的接口 rtsp.IBaseInSessionObserver ,使得接入时方便些
func (*AvPacket2RtmpRemuxer) OnSdp ¶
func (r *AvPacket2RtmpRemuxer) OnSdp(sdpCtx sdp.LogicContext)
func (*AvPacket2RtmpRemuxer) WithOnRtmpMsg ¶
func (r *AvPacket2RtmpRemuxer) WithOnRtmpMsg(onRtmpMsg rtmp.OnReadRtmpAvMsg) *AvPacket2RtmpRemuxer
func (*AvPacket2RtmpRemuxer) WithOption ¶
func (r *AvPacket2RtmpRemuxer) WithOption(modOption func(option *base.AvPacketStreamOption))
WithOption
TODO(chef): [refactor] 返回*AvPacket2RtmpRemuxer 202208
type DummyAudioFilter ¶
type DummyAudioFilter struct {
// contains filtered or unexported fields
}
func NewDummyAudioFilter ¶
func NewDummyAudioFilter(uk string, waitAudioMs int, onPop rtmp.OnReadRtmpAvMsg) *DummyAudioFilter
NewDummyAudioFilter 检测输入的rtmp流中是否有音频,如果有,则原样返回;如果没有,则制造静音音频数据叠加在rtmp流里面
@param waitAudioMs 等待音频数据时间,如果超出这个时间还没有接收到音频数据,则开始制造静音数据 @param onPop 注意,所有回调都发生在输入函数调用中
func (*DummyAudioFilter) Feed ¶
func (filter *DummyAudioFilter) Feed(msg base.RtmpMsg)
func (*DummyAudioFilter) OnReadRtmpAvMsg ¶
func (filter *DummyAudioFilter) OnReadRtmpAvMsg(msg base.RtmpMsg)
type GopCache ¶
type GopCache struct { MetadataEnsureWithSetDataFrame []byte MetadataEnsureWithoutSetDataFrame []byte VideoSeqHeader []byte AacSeqHeader []byte // contains filtered or unexported fields }
GopCache
提供两个功能:
- 缓存Metadata, VideoSeqHeader, AacSeqHeader
- 缓存音视频GOP数据
以下,只讨论GopCache的第2点功能
音频和视频都会缓存。
GopCache也可能不缓存GOP数据,见NewGopCache函数的gopNum参数说明。
以下,我们只讨论gopNum > 0(也即gopSize > 1)的情况。
GopCache为空时,只有输入了关键帧,才能开启GOP缓存,非关键帧以及音频数据不会被缓存。 因此,单音频的流是ok的,相当于不缓存任何数据。
GopCache不为空时,输入关键帧触发生成新的GOP元素,其他情况则往最后一个GOP元素一直追加。
first用于读取第一个GOP(可能不完整),last的前一个用于写入当前GOP。
最近不完整的GOP也会被缓存,见NewGopCache函数的gopNum参数说明。
----- gopNum = 1 gopSize = 2
first | first | first | 在后面两个状态间转换,就不画了 | | | | | | 0 1 | 0 1 | 0 1 | * * | * * | * * | | | | | | | last | last | last | | | | (empty) | (full) | (full) |
GetGopCount: 0 | 1 | 1 | -----
func NewGopCache ¶
NewGopCache
@param gopNum: gop缓存大小。
- 如果为0,则不缓存音频数据,也即GOP缓存功能不生效。
- 如果>0,则缓存[0, gopNum]个GOP,最多缓存 gopNum 个GOP。注意,最后一个GOP可能是不完整的。
func (*GopCache) GetGopCount ¶
GetGopCount 获取GOP数量,注意,最后一个可能是不完整的
func (*GopCache) GetGopDataAt ¶
func (*GopCache) SetMetadata ¶
type GopCacheMpegts ¶
type GopCacheMpegts struct {
// contains filtered or unexported fields
}
func NewGopCacheMpegts ¶
func NewGopCacheMpegts(uniqueKey string, gopNum int, singleGopMaxFrameNum int) *GopCacheMpegts
func (*GopCacheMpegts) Clear ¶
func (gc *GopCacheMpegts) Clear()
func (*GopCacheMpegts) Feed ¶
func (gc *GopCacheMpegts) Feed(b []byte, boundary bool)
Feed
@param b: 内部持有该内存块
func (*GopCacheMpegts) GetGopCount ¶
func (gc *GopCacheMpegts) GetGopCount() int
GetGopCount 获取GOP数量,注意,最后一个可能是不完整的
func (*GopCacheMpegts) GetGopDataAt ¶
func (gc *GopCacheMpegts) GetGopDataAt(pos int) [][]byte
type GopMpegts ¶
type GopMpegts struct {
// contains filtered or unexported fields
}
GopMpegts
单个Gop,包含多帧数据
type IRtmp2MpegtsRemuxerObserver ¶
type IRtmp2MpegtsRemuxerObserver interface { // OnPatPmt // // @param b: const只读内存块,上层可以持有,但是不允许修改 // OnPatPmt(b []byte) // OnTsPackets // // @param tsPackets: // - mpegts数据,有一个或多个188字节的ts数据组成 // - 回调结束后,remux.Rtmp2MpegtsRemuxer 不再使用这块内存块 // // @param frame: 各字段含义见 mpegts.Frame 结构体定义 // // @param boundary: 是否到达边界处,根据该字段,上层可判断诸如: // - hls是否允许开启新的ts文件切片 // - 新的ts播放流从该位置开始播放 // OnTsPackets(tsPackets []byte, frame *mpegts.Frame, boundary bool) }
type LazyRtmpChunkDivider ¶
type LazyRtmpChunkDivider struct {
// contains filtered or unexported fields
}
LazyRtmpChunkDivider 在必要时,有且仅有一次做切分成chunk的操作
func (*LazyRtmpChunkDivider) GetEnsureWithSdf ¶
func (lcd *LazyRtmpChunkDivider) GetEnsureWithSdf() []byte
func (*LazyRtmpChunkDivider) GetEnsureWithoutSdf ¶
func (lcd *LazyRtmpChunkDivider) GetEnsureWithoutSdf() []byte
func (*LazyRtmpChunkDivider) Init ¶
func (lcd *LazyRtmpChunkDivider) Init(msg base.RtmpMsg)
type LazyRtmpMsg2FlvTag ¶
type LazyRtmpMsg2FlvTag struct {
// contains filtered or unexported fields
}
LazyRtmpMsg2FlvTag 在必要时,有且仅有一次做转换操作
func (*LazyRtmpMsg2FlvTag) GetEnsureWithSdf ¶
func (l *LazyRtmpMsg2FlvTag) GetEnsureWithSdf() []byte
func (*LazyRtmpMsg2FlvTag) GetEnsureWithoutSdf ¶
func (l *LazyRtmpMsg2FlvTag) GetEnsureWithoutSdf() []byte
func (*LazyRtmpMsg2FlvTag) Init ¶
func (l *LazyRtmpMsg2FlvTag) Init(msg base.RtmpMsg)
type OnRtpPacket ¶
type OnSdp ¶
type OnSdp func(sdpCtx sdp.LogicContext)
type Rtmp2AvPacketRemuxer ¶
type Rtmp2AvPacketRemuxer struct {
// contains filtered or unexported fields
}
Rtmp2AvPacketRemuxer
用途: - 将rtmp流中的视频转换成ffmpeg可解码的格式
func NewRtmp2AvPacketRemuxer ¶
func NewRtmp2AvPacketRemuxer() *Rtmp2AvPacketRemuxer
func (*Rtmp2AvPacketRemuxer) FeedRtmpMsg ¶
func (r *Rtmp2AvPacketRemuxer) FeedRtmpMsg(msg base.RtmpMsg, arg interface{}) error
func (*Rtmp2AvPacketRemuxer) WithOnAvPacket ¶
func (r *Rtmp2AvPacketRemuxer) WithOnAvPacket(onAvPacket func(pkt base.AvPacket, arg interface{})) *Rtmp2AvPacketRemuxer
WithOnAvPacket
@param onAvPacket: pkt 内存由内部新申请,回调后内部不再使用
func (*Rtmp2AvPacketRemuxer) WithOption ¶
func (r *Rtmp2AvPacketRemuxer) WithOption(modOption func(option *Rtmp2AvPacketRemuxerOption)) *Rtmp2AvPacketRemuxer
type Rtmp2AvPacketRemuxerOption ¶
type Rtmp2AvPacketRemuxerOption struct { // TODO(chef): impl me 202206 TryInPlaceFlag bool // 尝试在原有内存上直接修改 }
type Rtmp2MpegtsRemuxer ¶
type Rtmp2MpegtsRemuxer struct {
// contains filtered or unexported fields
}
Rtmp2MpegtsRemuxer 输入rtmp流,输出mpegts流
func NewRtmp2MpegtsRemuxer ¶
func NewRtmp2MpegtsRemuxer(observer IRtmp2MpegtsRemuxerObserver) *Rtmp2MpegtsRemuxer
func (*Rtmp2MpegtsRemuxer) Dispose ¶
func (s *Rtmp2MpegtsRemuxer) Dispose()
func (*Rtmp2MpegtsRemuxer) FeedRtmpMessage ¶
func (s *Rtmp2MpegtsRemuxer) FeedRtmpMessage(msg base.RtmpMsg)
FeedRtmpMessage
@param msg: msg.Payload 调用结束后,函数内部不会持有这块内存
func (*Rtmp2MpegtsRemuxer) FlushAudio ¶
func (s *Rtmp2MpegtsRemuxer) FlushAudio()
FlushAudio
吐出音频数据的三种情况: 1. 收到音频或视频时,音频缓存队列已达到一定长度(内部判断) 2. 打开一个新的TS文件切片时 3. 输入流关闭时
func (*Rtmp2MpegtsRemuxer) UniqueKey ¶
func (s *Rtmp2MpegtsRemuxer) UniqueKey() string
type Rtmp2MpegtsTimestampFilter ¶
type Rtmp2MpegtsTimestampFilter struct {
// contains filtered or unexported fields
}
Rtmp2MpegtsTimestampFilter
(1). 通过dts和cts计算pts。 (2). 将数据包中的时间戳转换为从零开始的时间戳。
TODO(chef): [opt] 音频和视频公用一个base,避免以下情况: A: 6 7 ... V: 1 2 3 4 5 6 7 ... 另外,需要考虑音频比base还小的情况
func (*Rtmp2MpegtsTimestampFilter) Do ¶
func (f *Rtmp2MpegtsTimestampFilter) Do(frame *mpegts.Frame)
Do
@param frame: 直接修改frame中的dts和pts
func (*Rtmp2MpegtsTimestampFilter) Init ¶
func (f *Rtmp2MpegtsTimestampFilter) Init(uk string)
type Rtmp2RtspRemuxer ¶
type Rtmp2RtspRemuxer struct {
// contains filtered or unexported fields
}
Rtmp2RtspRemuxer 提供rtmp数据向sdp+rtp数据的转换
func NewRtmp2RtspRemuxer ¶
func NewRtmp2RtspRemuxer(onSdp OnSdp, onRtpPacket OnRtpPacket) *Rtmp2RtspRemuxer
NewRtmp2RtspRemuxer @param onSdp: 每次回调为独立的内存块,回调结束后,内部不再使用该内存块 @param onRtpPacket: 每次回调为独立的内存块,回调结束后,内部不再使用该内存块
func (*Rtmp2RtspRemuxer) FeedRtmpMsg ¶
func (r *Rtmp2RtspRemuxer) FeedRtmpMsg(msg base.RtmpMsg)
FeedRtmpMsg @param msg: 函数调用结束后,内部不持有`msg`内存块