Files
lkm/stream/trans_stream.go
2024-10-28 19:15:53 +08:00

141 lines
3.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package stream
import (
"github.com/lkmio/avformat/utils"
)
// TransStream 将AVPacket封装成传输流
type TransStream interface {
GetID() TransStreamID
SetID(id TransStreamID)
Input(packet utils.AVPacket) ([][]byte, int64, bool, error)
AddTrack(stream utils.AVStream) error
TrackCount() int
GetTracks() []utils.AVStream
WriteHeader() error
// GetProtocol 返回输出流协议
GetProtocol() TransStreamProtocol
// ReadExtraData 获取封装后的编码器扩展数据
ReadExtraData(timestamp int64) ([][]byte, int64, error)
// ReadKeyFrameBuffer 读取已经缓存的包含关键视频帧的输出流
ReadKeyFrameBuffer() ([][]byte, int64, error)
Close() ([][]byte, int64, error)
ClearOutStreamBuffer()
AppendOutStreamBuffer(buffer []byte)
// OutStreamBufferCapacity 返回输出流缓冲区的容量大小, 输出流缓冲区同时作为向sink推流的发送缓冲区, 容量大小决定向sink异步推流的队列大小;
OutStreamBufferCapacity() int
IsExistVideo() bool
}
type BaseTransStream struct {
//muxer stream.Muxer
ID TransStreamID
Tracks []utils.AVStream
Completed bool
ExistVideo bool
Protocol TransStreamProtocol
OutBuffer [][]byte // 完成封装的输出流队列
OutBufferSize int
}
func (t *BaseTransStream) GetID() TransStreamID {
return t.ID
}
func (t *BaseTransStream) SetID(id TransStreamID) {
t.ID = id
}
func (t *BaseTransStream) Input(packet utils.AVPacket) ([][]byte, int64, bool, error) {
return nil, -1, false, nil
}
func (t *BaseTransStream) AddTrack(stream utils.AVStream) error {
t.Tracks = append(t.Tracks, stream)
if utils.AVMediaTypeVideo == stream.Type() {
t.ExistVideo = true
}
return nil
}
func (t *BaseTransStream) Close() ([][]byte, int64, error) {
return nil, 0, nil
}
func (t *BaseTransStream) GetProtocol() TransStreamProtocol {
return t.Protocol
}
func (t *BaseTransStream) ClearOutStreamBuffer() {
t.OutBufferSize = 0
}
func (t *BaseTransStream) AppendOutStreamBuffer(buffer []byte) {
if t.OutBufferSize+1 > len(t.OutBuffer) {
// 扩容
size := (t.OutBufferSize + 1) * 2
newBuffer := make([][]byte, size)
for i := 0; i < t.OutBufferSize; i++ {
newBuffer[i] = t.OutBuffer[i]
}
t.OutBuffer = newBuffer
}
t.OutBuffer[t.OutBufferSize] = buffer
t.OutBufferSize++
}
func (t *BaseTransStream) OutStreamBufferCapacity() int {
return 0
}
func (t *BaseTransStream) TrackCount() int {
return len(t.Tracks)
}
func (t *BaseTransStream) GetTracks() []utils.AVStream {
return t.Tracks
}
func (t *BaseTransStream) IsExistVideo() bool {
return t.ExistVideo
}
func (t *BaseTransStream) ReadExtraData(timestamp int64) ([][]byte, int64, error) {
return nil, 0, nil
}
func (t *BaseTransStream) ReadKeyFrameBuffer() ([][]byte, int64, error) {
return nil, 0, nil
}
type TCPTransStream struct {
BaseTransStream
// 合并写内存泄露问题: 推流结束后, mwBuffer的data一直释放不掉, 只有拉流全部断开之后, 才会释放该内存.
// 起初怀疑是代码层哪儿有问题, 但是测试发现如果将合并写切片再拷贝一次发送 给sink, 推流结束后mwBuffer的data内存块释放没问题, 只有拷贝的内存块未释放. 所以排除了代码层造成内存泄露的可能性.
// 看来是conn在write后还会持有data. 查阅代码发现, 的确如此. 向fd发送数据前buffer会引用data, 但是后续没有赋值为nil, 取消引用. https://github.com/golang/go/blob/d38f1d13fa413436d38d86fe86d6a146be44bb84/src/internal/poll/fd_windows.go#L694
MWBuffer MergeWritingBuffer //合并写缓冲区, 同时作为用户态的发送缓冲区
}
func (t *TCPTransStream) OutStreamBufferCapacity() int {
utils.Assert(t.MWBuffer != nil)
return t.MWBuffer.Capacity()
}