feat: http-flv流的metadata与rtmp推流源的保持一致

This commit is contained in:
ydajiang
2024-12-24 20:12:18 +08:00
parent da7f084a2c
commit a13fb5a5c5
3 changed files with 22 additions and 55 deletions

View File

@@ -173,59 +173,26 @@ func (t *TransStream) flushSegment() ([]byte, bool) {
return FormatSegment(segment), key return FormatSegment(segment), key
} }
// GetHttpFLVBlock 跳过头部的无效数据返回http-flv块 func NewHttpTransStream(metadata *libflv.AMF0Object, prevTagSize uint32) stream.TransStream {
func (t *TransStream) GetHttpFLVBlock(data []byte) []byte {
return data[t.computeSkipBytesSize(data):]
}
// FormatSegment 为切片添加包长和换行符
func (t *TransStream) FormatSegment(segment []byte) []byte {
t.writeSeparator(segment)
return t.GetHttpFLVBlock(segment)
}
func (t *TransStream) computeSkipBytesSize(data []byte) int {
return int(6 + binary.BigEndian.Uint16(data[4:]))
}
// 为http-flv数据块添加长度和换行符
// @dst http-flv数据块, 头部需要空出HttpFlvBlockLengthSize字节长度, 末尾空出2字节换行符
func (t *TransStream) writeSeparator(dst []byte) {
// http-flv: length\r\n|flv data\r\n
// http-flv-block: |block size[4]|skip count[2]|length\r\n|flv data\r\n
// 写block size
binary.BigEndian.PutUint32(dst, uint32(len(dst)-4))
// 写flv实际长度字符串, 16进制表达
flvSize := len(dst) - HttpFlvBlockHeaderSize - 2
hexStr := fmt.Sprintf("%X", flvSize)
// +2是跳过length后的换行符
n := len(hexStr) + 2
copy(dst[HttpFlvBlockHeaderSize-n:], hexStr)
// 写跳过字节数量
// -6是block size和skip count字段合计长度
skipCount := HttpFlvBlockHeaderSize - n - 6
binary.BigEndian.PutUint16(dst[4:], uint16(skipCount))
// flv length字段和flv数据之间的换行符
dst[HttpFlvBlockHeaderSize-2] = 0x0D
dst[HttpFlvBlockHeaderSize-1] = 0x0A
// 末尾换行符
dst[len(dst)-2] = 0x0D
dst[len(dst)-1] = 0x0A
}
func NewHttpTransStream() stream.TransStream {
return &TransStream{ return &TransStream{
muxer: libflv.NewMuxer(nil), Muxer: libflv.NewMuxerWithPrevTagSize(metadata, prevTagSize),
header: make([]byte, 1024), flvHeaderBlock: make([]byte, 31),
headerSize: HttpFlvBlockHeaderSize, flvExtraDataBlock: make([]byte, 4096),
} }
} }
func TransStreamFactory(source stream.Source, protocol stream.TransStreamProtocol, tracks []*stream.Track) (stream.TransStream, error) { func TransStreamFactory(source stream.Source, protocol stream.TransStreamProtocol, tracks []*stream.Track) (stream.TransStream, error) {
return NewHttpTransStream(), nil var prevTagSize uint32
var metaData *libflv.AMF0Object
endInfo := source.GetStreamEndInfo()
if endInfo != nil {
prevTagSize = endInfo.FLVPrevTagSize
}
if stream.SourceTypeRtmp == source.GetType() {
metaData = source.(*rtmp.Publisher).Stack.MetaData()
}
return NewHttpTransStream(metaData, prevTagSize), nil
} }

View File

@@ -12,11 +12,11 @@ import (
type Publisher struct { type Publisher struct {
stream.PublishSource stream.PublishSource
stack *librtmp.Stack Stack *librtmp.Stack
} }
func (p *Publisher) Input(data []byte) error { func (p *Publisher) Input(data []byte) error {
return p.stack.Input(data) return p.Stack.Input(data)
} }
func (p *Publisher) OnDeMuxStream(stream utils.AVStream) { func (p *Publisher) OnDeMuxStream(stream utils.AVStream) {
@@ -49,12 +49,12 @@ func (p *Publisher) OnPartPacket(index int, mediaType utils.AVMediaType, data []
func (p *Publisher) Close() { func (p *Publisher) Close() {
p.PublishSource.Close() p.PublishSource.Close()
p.stack = nil p.Stack = nil
} }
func NewPublisher(source string, stack *librtmp.Stack, conn net.Conn) *Publisher { func NewPublisher(source string, stack *librtmp.Stack, conn net.Conn) *Publisher {
deMuxer := libflv.NewDeMuxer() deMuxer := libflv.NewDeMuxer()
publisher := &Publisher{PublishSource: stream.PublishSource{ID: source, Type: stream.SourceTypeRtmp, TransDeMuxer: deMuxer, Conn: conn}, stack: stack} publisher := &Publisher{PublishSource: stream.PublishSource{ID: source, Type: stream.SourceTypeRtmp, TransDeMuxer: deMuxer, Conn: conn}, Stack: stack}
// 设置回调, 接受从DeMuxer解析出来的音视频包 // 设置回调, 接受从DeMuxer解析出来的音视频包
deMuxer.SetHandler(publisher) deMuxer.SetHandler(publisher)
return publisher return publisher

View File

@@ -227,7 +227,7 @@ func TransStreamFactory(source stream.Source, protocol stream.TransStreamProtoco
// 获取推流的元数据 // 获取推流的元数据
var metaData *libflv.AMF0Object var metaData *libflv.AMF0Object
if stream.SourceTypeRtmp == source.GetType() { if stream.SourceTypeRtmp == source.GetType() {
metaData = source.(*Publisher).stack.MetaData() metaData = source.(*Publisher).Stack.MetaData()
} }
return NewTransStream(librtmp.ChunkSize, metaData), nil return NewTransStream(librtmp.ChunkSize, metaData), nil
} }